您的位置:首页 > 移动开发 > Unity3D

Unity3D开发总结一

2014-05-03 02:16 357 查看
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上! //这样维护性更好
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: