Unity3D开发总结一

相关网盘免费资源下载...

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")

 

 

 

***************切西瓜***************

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上!  //这样维护性更好

 

相关网盘免费资源下载...

 

 

 

你可能感兴趣的:(Unity3D开发)