纳金网
标题:
U3D 脚本概览
[打印本页]
作者:
晃晃
时间:
2011-9-23 15:39
标题:
U3D 脚本概览
一、 脚本概览 这是一个关于Unity内部脚本如何工作的简单概览。 Unity内部的脚本,是通过附加自定义脚本对象到游戏物体组成的。在脚本对象内部不同的函数被特定的事件调用。最常用的列在下面: Update: 这个函数在渲染一帧之前被调用。这里是大部分游戏行为代码被执行的地方,除了屋里代码。 FixedUpdate 这个函数在每个物理时间步被调用一次。这是处理基于物理游戏行为的地方。 在任何函数之外的代码: 在任何函数之外的代码在物体被加载的时候运行。这个可以用来初始化脚本状态。 注意:文档的这个部分假设你是用Javascirpt,参考用C#编写脚本获取如何使用C#和Boo编写脚本的信息。 你也能定义事件句柄。它们的名称都以On开始,(例如 OnCollisionEnter)。为了查看完整的预定义事件的列表,参考MonoBehaviour文档。 概览:常用操作 大多数游戏物体的操作是通过游戏物体的Tranform和/或Rigidbody来做的。在行为脚本内部它们可以分别通过transform和rigidbody访问。因此如果你想绕着Y轴每帧旋转5度,你可以如下写: Function Update() { Transform.Rotate(0,5,0); } 如果你想向前移动一个物体,你应该如下写: Function Update() { Transform.Translate(0,0,2); } 概览:跟踪时间 Time类包含一个非常重要的类变量,称为deltaTime,这个变量包含从上一次调用Update或FixedUpdate(根据你是再Update函数还是再FixedUpdate函数中)到现在的时间量。 所以对于上面的例子,修改它使这个物体以一个恒定的速度旋转而不依赖于帧率: Function Update(){ Transform.Rotate(0.5*Time.deltaTime,0); } 移动物体: Function Update(){ Transform.Translate(0,0,2*Time.deltaTime); } 如果你加或减一个每帧改变的值,你应该将它与Time.deltaTime相乘。当你乘以Time.deltaTime时,你实际表达:我想以10米/秒移动这个物体而不是10米/帧。这不仅仅是因为你的游戏将独立于帧率运行,同时也是因为运动的单位容易理解。(10米/秒) 另一个例子,如果你想随着时间增加光照的范围。下面的表达式,以2单位/秒改变半径, Function Update(){ Light range=2.0*Time.deltaTime; } 当通过力出力刚体的时候,你通常不必用Time.deltaTime乘,因为引擎已经为你考虑到了这一点。 概览:访问其他组件 组件被附加到游戏物体。附加Renderer到游戏物体使他在场景中渲染,附加一个Camera使他变为相机物体。所有的脚本都是组件,因为它们能被附加到游戏物体。 最常用的组件可以作为简单成员变量访问: Component 可如下访问 Transform transform Rigidbody rigidbody Renderer renderer Camera camera(only on camera objects) Light light(only on light objects) Animation animation Collider collider ……等等。 对于完整的预定义成员变量的列表,查看Component,Behaviour和MonoBehaviour类文档。如果游戏物体没有你想取回类型的组件,上面的变量将被设置为null。 任何附加到一个游戏物体的组件或脚本都可以通过GetComponent访问。 Transform..Translate(0,1,0); //等同于 GetComponent(Transform).Translate(0,1,0); 注意transorm和Transform之间大小写的区别,前者是变量(小写),后者是类或脚本名称(大写),大小写不同使你能够从类和脚本名中区分变量。 应用我们所学,你可以使用GetCompent找到任何附加在同一游戏物体上的脚本和组件,请注意要使下面的例子能够工作,你需要有一个名为 OtherScript的脚本,其中包含一个DoSomething的函数,OtherScript脚本必须与下面的脚本附加到相同的游戏物体上。 //这个在同一个游戏物体上找到名为OtherScript的脚本 //并调用它上面的DoSomething Function Update();{ otherScript=GetComponent(otherscript); otherScript DoSomething(); } 概览:访问其他游戏物体 大多数高级的代码不仅需要操作一个物体。Unity脚本接口有各种方法来找到并返回其他游戏物体和组件。在下面,我们假定有一个名为OtherScript.js的脚本附加到场景的游戏物体上, Var foo=5; Function DoSomething(param:String){ Print(param+”with foo:”+foo); } 1. 通过检视面板赋值引用。 你可以通过检视面板赋值变量到任何物体。 //变换拖动到target的物体 Var target:Transform; Function Update() { target.Translate(0,1,0); } 你也可以在检视面板中公开到其他物体的引用。下面你可以拖动一个包含OtherScript的游戏物体到检视面板中的target槽。 //设置在检视面板中赋值的target变量上foo,调用DoSomething. Var target:OtherScript; Function Update() { //设置target的物体的foo变量 Target.too=2; //调用target上的DoSomething target.DoSomething(“Hello”); } 2. 通过物体层次定位 对于一个已存在的物体,可以通过游戏物体的Transform组件来找到子和父物体: //找到脚本所附加的 //游戏物体的子”Hand” Transform.Find(“Hand”).translate(0,1,0); 只在层次视图中找到这个变换,你可以使用GetComponent来获取其他脚本, //找到名为”Hand”的子物体 //在附加到它上面的OtherScript中,设置foo为2 Transform.Find(“Hand”).GetComponent(OtherScript)DoSomething(“Hello”); //找到名为”hand”的子 //调用附加到它上面的OtherScript脚本的DoSomething Transform.Find(“Hand”).GetComponent(OtherScript).DoSomething(“Hello”); //找到名为”hand”的子 //然后应用一个力到附加在hand上的刚体 Transform.Find(“Hand”).rigidbody.Addforce(0,10,0); 你可以循环所有的子。 //变换的所有子向上移动10个单位 For(var child:Transform in transform) { Child.Transform(0,1,0); } 参考Transform类文档获取更多信息。 3. 根据名称或标签定位 你可以使用GameObject.FindWithTag和GameObject.FindGameObjectsWithTage搜索具有特定标签的游戏物体。使用GameObject.Find根据名称查找物体 Function Start() { //按照名称 Var go= GameObject.Find(SomeGuy”); go.transform.Translate(0,1,0) //按照标签 Var player=GameObject.FindWithTag(“Player”); Player.transform.Translate(0,1,0); } 你可以在结果上使用GetComponent,在找到的游戏物体上得到任何脚本或组件。 Function Start() { //按名称 Var go=GameObject.Find(“SomeGuy”); Go.GetComponent(OtherScript).DoSomething(); //按标签 Var player =GameObject.FindWithTag(“Player”); Player.GetComponent(OtherScirpt).DoSomething(); } 一些特殊的物体有快捷方式,如主相机使用Camera.main。 4. 作为参数传递 一些实践消息在事件中包含详细信息。例如,触发事件传播碰撞物体的Collider组件到处理函数。 OnTriggerStay给我们一个到碰撞器的引用。从这个碰撞器我们可以获取附加到其上的刚体。 Function OnTriggerStay(other:Collider){ //如果使用另外一个碰撞器也有一个刚体 //应用一个力道它上面 if(other.rigidbody){ other.rigidbody.AddForct(0,2,0); } } 或者我们可以通过碰撞器获取附加在同一物体上的任何组件 Funtion OnTriggerStay(other:Collicer){ //如果另一个碰撞器附加了OtherScript //调用它上面的DoSomething //大多数时候碰撞器不会附加脚本 //所以我们需要首先检查以避免null引用一场。 If(other.GetComponent(OtherScript)){ Other.Get(Comeponent(OtherScript).DoSomething(); } } 注意通过上述例子中的other变量,你可以访问碰撞物体中的任何组件。 5. 一种类型的所有脚本 使用Object.FindObjectsOfType找到所有具有相同类或脚本名称的物体,或者使用Object.FindObjectOfType找到这个类型的第一个物体。 Function Start() { //找到场景中附加了OtherScript的任意一个游戏物体 Var Other:OtherScript=FindObjectOfType(OtherScript); Other.DoSomething(); } 概览:向量 Unity使用Vector3类统一表示全体3D向量。3D向量的不同组件可以通过x,y和z成员变量访问。 Var aposition:Vector3; aposition.x=1; aposition.y=1; aposition.z=1; 你也能够使用Vector3构造函数来同时初始化所有组件。 Var aposition=Vector3(1,1,1,);相同 单个向量上的操作可以使用下面方式访问: Var direction=Vector3.up//与Vector3(0,1,0)相同 单个向量上的操作可以使用Vector3类函数; TheDistance=Vector3 Distance(oneVector,otherVector); (注意你必须在函数名之前写Vector3来告诉JavaScript在哪里找到这个函数。着适用于所有类函数。) 你也可以使用普通数学操作来操纵向量。 Combined=Vector1+Vector2; 查看Vector3类文档获取完整操作和可用属性的列表。 概览:成员变量&全局变量变量 定义在任何函数之外的变量是一个成员变量。在unity中这个变量可用通过检测面板来访问。任何保存在成员变量中的值也可以自动随工程保存。 Var member variable=0.0; 上面的变量将在检视面板中显示为名为“member variable”的数值属性。 如果你设置变量的类型为一个组件类型(例如transform,rigidbady,collider,任何脚本名称,等等)然后你可以在检视面板中通过拖动一个游戏物体来设置它们。 Var enrmy :Transform; Function Update() { If(Vector3.Distance(enemy.position,Transform.position)<10){ Print(“I seese the enemy is near!”); } } 你也可以创建私有成员变量。私有成员变量可用用来存储那些在该脚本之外不可见的状态。私有成员变量不会被保存到磁盘并且在检视面板中不能编辑。当它被设置为调试模式时。它们在检视面板中可见。着允许你就像一个实时更新的调试器一样使用是有变量。 Private var lastCollider:Collider; Private var lastCollisionEnter(collider.info:collision){ lastCollider=collisioninfo.other } 全局变量 你也可以使用static关键字创建全局变量。 着创造了一个全局变量,名为someClobal。 //TheScriptName.js中 的一个静态变量 Static var someGlobal=5; // 你可以在脚本内部像普通变量一样访问它 Print(someGlobal); someGlobal=1; 为了从另一个脚本访问它,你需要使用这个脚本的名称加上一个点和全局变量名。 Print(someGlobal); TheScriptName someGlobal=10; 概览:实例化 实例化,复制一个物体。包含所有附加的脚本和整个层次。它以你期望的方式保持引用,到外部物体引用的克隆层次将保持完好,他克隆层次上到物体的引用将映射到克隆物体。 实例化是难以置信的快和非常有用的。因此最大化地使用它是必要的。 例如,这里是一个小的脚本,当附加到一个带有碰撞器器的缸体上时将销毁它自己并实例化一个爆炸物体 Var explosion :transform; //当碰撞发生时销毁我们自己 //并声称一个爆炸预设 Function OnCollisionEnter() { Destroy(gameobject); Var theClonedExplosion:transform; TheClonedExplosion=instantlate(explosion.transform.position,transform.rotation); } 实例化通常与预设一起使用。
作者:
Asen
时间:
2011-9-29 09:26
一个字 乱
作者:
彬彬
时间:
2011-10-7 11:31
看的眼花
作者:
奇
时间:
2012-1-19 23:03
鉴于你今年的良好表现,新年将至,别人都在祝福你新年快乐,我觉得换一种新颖的方式祝福你,那就是:天天开心,事事顺利,雷打不动的祝福属于你!
作者:
C.R.CAN
时间:
2012-1-29 23:19
新年的风,吹散你的阴霾;新年的雨,冲刷你的无奈;新年的雾,锁定你的失败;新年的日,照耀你的期待。新年到来,幸福怀揣,新年快乐,响彻天外!
作者:
奇
时间:
2012-2-8 23:27
俺是新人,这厢有礼了!
作者:
tc
时间:
2012-5-9 23:26
赞一个,哈哈
作者:
晃晃
时间:
2012-6-1 23:18
很经典,很实用,学习了!
作者:
C.R.CAN
时间:
2012-6-28 23:25
有意思!学习了!
作者:
晃晃
时间:
2012-8-24 23:32
很经典,很实用,学习了!
作者:
晃晃
时间:
2012-10-29 23:22
心中有爱,爱咋咋地
作者:
晃晃
时间:
2012-11-1 23:27
好可爱的字,学习了
作者:
晃晃
时间:
2012-11-12 23:20
佩服,好多阿 ,哈哈
作者:
菜刀吻电线
时间:
2013-2-16 23:29
其实楼主所说的这些,俺支很少用!
作者:
菜刀吻电线
时间:
2013-2-26 23:29
响应天帅号召,顶
作者:
C.R.CAN
时间:
2013-3-2 23:40
加精、加亮滴铁子,尤其要多丁页丁页
作者:
tc
时间:
2013-3-5 23:18
我是老实人,我来也!
欢迎光临 纳金网 (http://wwww.narkii.com/club/)
Powered by Discuz! X2.5