Unity3D开发总结一

Unity3D开发总结一
分类: Unity3D开发 2013-02-27 15:20 1461人阅读 评论(0) 收藏 举报
1.太空射击游戏开发
a. 场景操作与Maya一样,F居中,场景操作与Maya一致
b.  unity3d的Project可以理解为C#的项目
c. FirstPerson contraller需要在自定义键盘中定制
 
2. C#开发
d.  Unpdata 每帧计算一次,  start -->脚本绑定的object初始化的时候执行一次
e. 每个gameobject上可以绑定多个script
f. script 的类名应与所绑定的object的对象名称一致,eg:
public class objectA: Monobehavior....
g. 也可以直接将脚本拖曳到object上
f. 类中的public属性在 inspector中就成为script组件的属性了
 
3.
a.  2D 游戏-->正交投影camera,
b. project相当于资源-->不一定会出现在Heriachy中,Hierarchy中的object就是游戏场景中的物体和节点
c. Time类.deltaTime -->只读(秒),就是本帧的持续时间
d.
Updata :一定显示,也解算(相当于realtime)
lateUpdata :
FixUpdata: 在刚体解算的时候使用该方法,而不是Updata-->相当于everyFrame,
e. 运行的时序是(从前到后): FixUpdata--->Updata-->lateUpdata
4.
f. Vector.up  Vector.down  Vector.left ..是归一化的矢量
g.   tranform.position--->是当前类所绑定的对象的position ,transform是当前绑定对象的根节点(下面可以有很多组件的子节点),
h.  Destroy(this.GameObject) --->回收当前实例中的GameObject属性对象
i.  prefab-->克隆对象(包括相关的所有component),整体打包
j.  script组件也是gameobject
h.  AudioSource可以Add到任何object上,生存期和被绑定的object相同,主背景音乐一般加到一个空gameobject上或者Maincamera上
i.  OnGui() --->创建界面的方法,每帧都重构,eg:
   if(Gui.Button(new Rect(0,60,100,50),“pause”)  Audio.pause();  //检测Button是否按下
j. Add组件的原则是-->和什么ojbect/实例相关就Add到什么ojbect/实例上
k.  void start()
{  //本实例创建时的相关设置
}
 
l.  x=Random.Rang(-8.0f,8.0f);
   y=6.5f;
    z=0.0f;
   transform.position=new vector(x,y,z);  //transform.position是世界坐标
m.
float amiToMove =currentSpeed*Time.deltaTime;
transform.Translate(vector.down*amiToMove);   //在当前位置的基础上偏移(相对位移)

n.   particle中不勾选simulate in worldspace则particle就可以随object(发射体)移动,反之不行

o.  score(得分),生命值等--->应该设置为全局静态变量

p. onGUI()
{ //界面元素每帧都重构}
q.  void onTrggerEnter(collider  otherobject)//在有穿插碰撞的时候检测,collider  otherobject是被碰撞物体
r.  script必须拖曳,且和某个object绑定后才能生效
s.  场景Build 后才能实现  loadLevel(场景序号) //scene切换
t. project就是资源工厂(进行各种资源的打包,重组)--->只为场景提供资源,与Hierachy没有直接关系
u.  Transform.Translate--->使用local坐标,如果使用world坐标应该如下:
    transform.translate(vector3.down*aimToMove,space.world)
v.  Random.Rang(0,1)..
w.  transform.Rotate 、transform.translate 都是相对偏移量
x.  while ()
{   yield  reture  0; // 可以在每一个遍历或者循环中都返回一次到调用处,类似于一个迭代子,好处是不用全部完成后再返回所有的数据,节约时间 }
y.  tranform.translate( ) //是个动作,相对位移
    local.position  //是object的当前世界坐标
z. prefab //好处是:instance化,节约计算量; 可以组合打包为新的对象进行使用
 
4.
a. 创建Prefab物体时候与Maya创建instance一样,最好将其Freeze,而且unity3d中许多物体初始创建时,最好Freeze,不要使用默认的创建位置
b. this.gameobject才是当前script类绑定的ojbect
 
5.碰撞检测的注意事项
c.  要进行碰撞,两个物体必须都有Collsion组件,要发生碰撞检测事件的话,其中之一还必须为rigidbody
d. 两个物体如果只想实现表面碰撞(不穿透)那么不要勾选OnTrigger,此时要使用 OnCollsionEnter()方法来检测碰撞事件;
e. 如果想两个物体既要发生碰撞,而且可以穿透(运动不被对方所阻挡),那么要勾选OnTrigger,此时要使用OnTriggerEnter()方法来检测碰撞事件;
 
6
f.得到tranform组件的方法:
(enemy)otherCollider.GetComponent("enemy") //"enemy"是Gameobject 的name,此方法限于本gameobject中所绑定的组件
7
g.  yield -->一般只和 startCoroutine() 配合使用,因为 yield语句返回IEnumerator
h.
  while()
{ yield return 0; //0 只是停止一帧;  waitForSecond(秒)指定停止多少秒  }
 
i.  只要涉及到线程的等待就要涉及多线程startCoroutine()方法-->这样不会阻塞主调用线程的进程
j. 但是js中不需要多线程程startCoroutine()方法实现等待功能,JS中直接让主线程调用一个方法(该方法中有yield,或者waitForSecond(秒)方法就可)
 
 
********************坦克克星****************
1.
a. 显示2D贴图的spriteMesh -->是个非常有用的东西,在制作2D Game中平面化的 object的必杀器;
spriteMesh可以和cube 结合使用,也可以直接创建 spriteMesh,然后再添加collsion组件
b. 将texture-->直接拖曳到object上-->就产生响应的材质
c.  Material中也能加入script 对响应的材质进行控件// d.
e.
var ani=GetComponent("anisprite")  //用于获得组件名称为script脚本组件实例 ,ani 即为该实例的应用,通过ani 可以对ani中属性进行设置
    ani.anisprite(3,10,0,0);//直接调用ani实例中的方法,可以理解为游戏运行时所有与gameobject绑定的组件都实例化了,包括script组件;
                                    //anisprite是个功能类,
f.  Unity3D,script组件本质:
       GameObject(同时有A,B两个script组件)
  scriptA        scriptB
当场景运行时,scriptA类和scriptB类都进行实例化,-->充当工具类来使用,所以就可以通过e中的方式来型号调用方法
 
g.  scriptMode-->来显示图片序列动画
h. transform.lcocalEulerAngles.z> 310(角度) //lcocalEulerAngles是object的自身坐标的角度值(标量)
i.  var  fwd=transform.transformDirection(vector3.left)  //将当前object的local 坐标转换为世界坐标系下的坐标
    physics.Raycast(transform.position,fwd,10)) //Raycast检测从某个方向到某个距离之内是否有物体被ray射中!
                                                          //transform.position 是从什么位置发射;
                                                         //fwd 朝什么方向(都为世界坐标)
j.   function start()
{    AudioSource.PlayclipAtPoint(explosion,vector(0,0,-5)) //在某点播放声音explosion,   }
 
2.
k. 废弃的ojbect要及时destroy掉, destroy(gameobject,0.5)//0.5秒后gameobject被销毁
l.   同时按住两个以上的键的检测方法:
     if(input.GetButton("Jump"))  //是否按下空格键
        {   if(Input.GetAxis("Horizontal")>0  //按下空格键的同时是否按下水平键
        }
 
m.
rigid  body; //定义一个rigid物体
body.velocity.x=3*speed;  // 该rigid物体的.velocity.x设置为3*speed
n.
如果如图所示要跑到沿着炮管发射,可以如下:
 myprojecttile=instantiate(projecttile,transform.position+fwd,transform.rotation);//  transform.rotation是让当前炮弹的倾角和炮管的倾角transform.rotation一致
 myprojecttitle.velocity=fwd*20;  //myprojecttitle炮弹是rigid所以可以使用此方式,使其获得一个初速度
 
2.
a.tag标签的功能类型与组的使用,unity中可以使用name或者tag来标示一个object
b. Gameobject.FindwithTag("tanko");  //在整个场景中寻找名为tanko的物体,返回值是一个数组(因为可能会找到多个物体)
c.  Application.Quit() //退出场景
 
 
 
 
****************************Unity3D中的动画系统*******************************
1.
a.  unity中可以导入fbx模型
b.  gameObject.animation.playQueued("Aim") //执行Aim动画片段
c.
gameObject.animation.playQueued("Aim");
gameObject.animation.playQueued("Idel") ;   //顺序执行 Aim动画片段和Idel片段
d.  play-->自定义键// Negative Button 是松开键; Postitive Button是按下键
e.  Animation编辑窗口 //shift+滚轮: 纵向放大视图   ctl+滚轮:横向放大视图
f.  在动画编辑栏上部双击-->可以添加某个触发事件的方法
g.  动画clip
  clip.setcurve("",typeof(Transform),localPosition.x,curve)  //setcurve方法可以对curve自定义动画曲线实现加载,并可以绑定到指定的属性上去;
h. 动画clip和music一样只需要在start中执行一次就可以一直往后播放,不用累计
 
 
*****************************投篮游戏*****************************i.
1.
a. 动画组件上sprite Animation-->分割连续的动画为多个clip
b. 让gameobject旋转的方法:
   transform.Rotate(new vector3(0,speed*time.deltatime*input.GetAxis("Horizontal"),0)) //transform.Rotate与transform.translate一样是让当前object进行位置或者角度偏移一个相对量,
c.  gameobject.transform.RotateAround(new vector3(沿着什么点),new vector3(0,1,0沿什么轴),speed*Time.deltaTime*input.GetAxis("Horizontal")偏移旋转多少角度);
d. object.position   object.rotation  //都是世界坐标的位置、角度量
e.  主动刚体才要设置rigig ,被动刚体不要设置rigid
f.只有具有collision组件的ojbect才能添加 physicMaterial
g.  OnGUI-->可以放在任何script中,这样只要显示与某个object相关的GUI
h.  一般在被碰撞物体中做碰撞检测,
i.  只要单次播放的声音,可以使用AudioSource.playAudioAtPoint //比如在爆炸事件中单次播放一次
 
 
 
**************************PlatForm**************************
 
1.
a. unity中世界坐标的Z轴正方向向屏幕里面 X
b. render.material.mainTextureScale=vector2(0.1,1) //  mainTextureScale是贴图UV平铺的坐标
    render.material.mainTextureOffset=vector2(0.1,0)// mainTextureOffset是贴图的offset量
c.  transform.renderer.material=runMaterial; // transform好像是当前脚本绑定物体的根节点,切换当前object的材质为runMaterial材质
   aniPlay.ansprite(10,10,true);//  通过GetComponent("aniPlay")得到的aniplay实例(工具类)
d. input .GetAxis("Horizontal") >0 //自定义的方向键向右 Negeative
   input .GetAxis("Horizontal") >0 // 自定义的方向键向左 Positive
 
2.
e.  character contraller -->主角色的物理特征控制器
f. character控制器属性 //contraller.IsGround 撞地检测;jumpEnable=false -->使用左右键控制移动
g.   character运行三部曲:首先判读是否接地-->根据input.GetAxis获得速度方向-->根据速度方向,确定人物动画方向-->将速度方向*均匀的速度(水平或者垂直)
--->最后将速度变化  v-=time.delta*g
h.  由于空中不能Jump-->所以Jump放在OnGround中获得--->且只有一次,而空中不获得velocity
i. 单次播放sound的经典模式:
  void playsound(soundName)
{  AudioSource.playclipAtPoint(soundName,vector3(0,0,-10));
    yield waitForSecond(soundName.length);  //将sound播放soundName.length的时长
}
j. time.delta-->其实对每一个帧无太大意义;
  updata()中每帧中所有的方法只调用计算一次,其实与时间无关,time.deltatime只是改帧持续的时间;
 
k. updata() 每帧执行与time.deltatime关系的原理图:
<----------------------------------每帧的时间长度(time.deltatime)-------------------------------------------->
每帧开始时:
计算所有  <----------->期间完成于线程和yield、waitForSecond相关的方法<------------->该帧结束
updata的方法            
 
例如:
  void updata()
{  transform.translate(vector3.left*speed); // 帧开始计算一次
    aniplay.anisprite(0,0,false); //因为anisprite方法与线程有关,所有一直要持续到帧结束
                                          //
}
 
 
 
 
*********************机器人之战*********************
 
2.
a. //ayercontraller.cs
  updata()
{
if(jumpEnable)
{  aniplay.anisprite(10,3,0,30,1,false) ;       }//调用aniplay.cs中的anisprite方法,因为anisprite是在updata中每帧更新的,所以相当于
                                                    //playcontraller调用多线程aniplay中的updata方法来执行动画
}
b.  Charater contraller碰撞物体的核心代码:
velocity.y -=gravity*Time.deltaTime;// 每帧速度变化
controller.Move(velocity*Time.deltaTime); //每帧位移的变化
c.   if(input.GetAxis("Horizontal")&&!input.Getkey("Z");  //按下水平键,且没有按下z键
d.  Transform.position// 当前object的位置
     laserPosRight.transform.position  //某个gameobject的位置(且出现在当前script的引用中)
e. Mathf.cos(15.0/180*3.14) //Mathf.cos要求用弧度
 
3.动画播放可以分为:
a.  动态装载播放,例如:
player左右上下跳,-->不同条件装载相应的Material,然后调用线程anisprite来播放动画
b. 静态绑定动画,例如:
子弹instance物体-->直接在gameobject上绑定anisprite组件并且指定好固定参数
 
3.
h. 碰撞是否为isTrigger都会发生碰撞
i.  var  objects= GameOject.FindGameobjectwithTag("rock")  //返回一个数组
j.  transform.translateDirection(direction) //将自身坐标转换为世界坐标
 
4.对于敌人script编写的原理
a. 设置敌人的几种状态,例如:行走、攻击、被杀、
b. 根据各种事件来设置状态
c. 设计达到各种状态所要播放的动画和行为
 
5.自身旋转的两种方式:
a.  transform.localEulerAngle3.Z+=amtToRotate ;
b. transform.localRotate(vector3...);
 
6.
a. 空EmptyObject-->只有且只有是Transform类型,才可以用于定位,例如可以作为发射口(炮弹)的定位器
b.  深度camera-->要使用layer,Masker
c.  如果只将scene的某个部分导入到另一个scene-->可以只将scene中的物体(例如:player) -->生成prefab,然后到处与player prefab相关的资源(不包括scene)为
Assert,-->然后在另一个场景中导入即可
 
7.
d. 如果IsTrigger被勾选,那么只能使用OnTriggerEnter() 来检测
e. 一个子弹对应一个其上面绑定的脚本实例(一个脚本随着instance的物体被实例化成多份)
f.  OnTriggerEnter(other: collider)
{  if( other.tag=="player“&&name=="trigger")  //“name=="trigger": 被碰撞的物体(本脚本绑定的主物体)  ;   other.tag=="player“: 主动碰撞物体
{...}
}
g. 类似静态方法/属性-->不用到绑定对象,就可以供全局使用
 
8.
a. myTop=GameObject.Find("/player/top");    //    /(Hirechy根)player/top(指定Gameobject下的组件)
    myTop.active=false;  // 不可见
 
 
 
*******************GUI设计*******************
1.
b.   每个UI(对话框都是一个实例)
c.  if(input.GetKey(Keycode.m)) //检测M键是否被按下
d.  GUI.DragWindow() //可以拖动窗口实例
e.  GUI.skin  与C#中的skin很相似
f.   窗口绘制的主方法
DoMyWindow(int  windowID)
{  intToolBar=GUI.ToolBar(tabButton,inToolBar,StoolBars,GUI.skin.Getstyle("TabButton"));  //tabButton 是button 的类型,Getstyle()是使用指定的皮肤
}
 
 
******************愤怒的小鸟******************
1.
a. GUITexture-->可以直接作为界面的logo使用
b. GUITexture可以在一个scene中添加多个,通过Z轴(深度)的前后进行叠加
c. GUITexture与其他GameObject一样
d. if(input.GetMoveButton(0))  //检测是否点击鼠标左键
 
2.
e.    drawTexture 的坐标是:  X轴正方向朝屏幕右边;Y轴正方向朝屏幕的下方 //与C#的UI坐标一致
      screen坐标是:  X轴正方向朝屏幕右边;Y轴正方向朝屏幕的上方方
f.  GUI.depth=-1; //可以设置GUI的深度值(前后)
g.  Sprite可以直接使用(如果不需要碰撞)  //可以不用与Cube结合使用
h.  invokeRepeating("Move",2, time)  //invokeRepeating方法 -->在2秒以后,每time秒后调用Move方法,类似于线程
i.  camera.main.screenPointToRay() //将屏幕上的一点转换为射线
j.   object 层次:
   transform.gameobject.collider.isTrigger=true;  //transform.是当前脚本绑定节点的根,.collider是gameobject下的collision组件
k. 事件控制场景机制下/物体的状态设置很重要,也很方便
 
3.
a. 画连续曲线时,不可能一次性设置太多vertex(eg: lineRender.setVertexCount(100)) ..一次性设置100个点太多,绘制时会出现问题);
而是要如下绘制:
lineRender.setVertexCount(index+1) //每次设置第index+1的点
lineRender.setPosition(index,position);  //设置第index点的位置
b.  object有collision后只能检测碰撞,不会产生碰撞的互动效果(例如:被碰飞),要有互动效果的话,必须加rigid组件
 
4.
c.  myDigit=instantiate(digit....) //获得object
   myScript=myDigit.transform.Getcomponent(digtDisplay)  //获得与myDigit绑定的digitDisplay脚本组件实例或引用
   if(playerPrefs.Haskey("HighScore"))  //本地永久化储存场景
myScript.mystringScore=palyerPrefs.GetInt("HighScore").toString();  //从本地永久化数据中得到HighScore 数据                                          
                                                                                                  //并且设置myscript脚本实例的mystringScore属性值
 
d.  if(playprefs.Getint("HighScore")<myscore)  playerPrefs.setInt("Highscore",myscore);  //Getint得到本地数据;setIn写入本地化数据
 
 
 
***************切西瓜***************
1.
a. input.mousePosition.x //相对于屏幕坐标
b.  camera(那个camera).main.screenToWorldPoint(将屏幕坐标转换为world坐标)(new vectors(input.mousePositon.x...  ))  ; //input.mousePositon.x是屏幕坐标
c.  instantiate(myRay,middleposition,Queterion.AngleAxis(angle*180/3.14,vector3.forward))  //AngleAxis-->绕着forward矢量旋转(angle*180/3.14)角度
 
2.
d.
if(isclicked)
{
   if(ismouseDown)
   {  var ray:Ray=camera.main.screenPointToRay(input.mousePoint);  //将屏幕上的鼠标坐标转换为一条射线
       var  hit:RayCastHit;
       if(collider.Raycast(Ray...))  //判断刀是否切到水果,刀在每帧判断一次
   }
}
e. 当判断左键点击下去的位置(firstposition),经过一段时间后,左键再放开的位置(secondPosition)-->左键按下到放开这个过程可能会贯穿多帧,
不一定是在同一帧内完成的;除非按下到放开这个过程的time<=time.delta.Time(每帧的时长)
f.  void  start()
{    invokeReapting("Move",0,3.2);  //该方法只需要在start()中调用,然后每3.2秒,自动调用一次Move方法,
}
 
3.
g.  在script中获取script所绑定对象的本身:  使用(this): transform.local.....即可
h. 在script中获取其他节点,可以使用如下方法:myApple=instantiate(....)  ;
                                                                 myApple.transform.rigidbody...   ;  //transform类似于根节点
 
 
5.脚本的拆分原则:
如果一个脚本中(按对对象object的操作功能可以进行进一步的划分),那么就没必要将所有操作功能都写在一个大class中!
可以按照功能的进一步划分,写在多个子Class中,然后再统一绑定到该object上!  //这样维护性更好
 

 

技术详情点击:  http://url.cn/RTBgdY
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值