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上! //这样维护性更好 相关网盘免费资源下载...