Uniyt脚本参考.docx
《Uniyt脚本参考.docx》由会员分享,可在线阅读,更多相关《Uniyt脚本参考.docx(26页珍藏版)》请在冰豆网上搜索。
Uniyt脚本参考
Unity_脚本参考
第一章概述
Unity中的脚本(Script)由附加到游戏对象(GameObject)的自定义脚本对象(Custom
ScriptObject)组成,它们又被称为行为。
脚本对象中各种函数被称为必然事件(Certain
Event)。
常用的必然事件有如下三个:
1、Update:
该函数在渲染帧之前被调用,大部分的游戏行为代码都在这里执行,除了
物理代码。
2、FixedUpdate:
该函数在每进行一次物理时间步调时被调用,它用来执行基于物理的
游戏行为。
3、Codeoutsideanyfunction:
这类函数在对象加载时被调用,它们用来执行脚本状态
的初始化工作。
你可以自定义事件处理器(EventHandler),它们都以“On”前缀进行命名,例如:
OnCollisionEnter。
第二章常用操作
大部分游戏对象的操作都是通过它们的Transform和Rigidbody实例来实现的,我们可
以在脚本中直接通过成员变量transform和rigidbody来访问这两个实例。
例如:
要实现游戏
对象每帧以Y轴旋转5度的效果,可以进行如下编码:
functionUpdate()
{
transform.Rotate(0,5,0);
}
_________________________________C#
usingUnityEngine;
usingSystem.Collections;
publicclassBox:
MonoBehaviour
{
voidUpdate()
{
transform.Rotate(0,5,0);
}
}
____________________________________
让游戏对象向你移动,可进行如下编码:
functionUpdate()
{
transform.Translate(0,0,2);
}
______________________________________C#
usingUnityEngine;
usingSystem.Collections;
publicclassBox:
MonoBehaviour
{
voidUpdate()
{
transform.Translate(0,5,0);
}
}
_____________________________________________
第三章时间
Time类包含了一个重要的类变量deltaTime,它表示距上一次调用Update或FixedUpdate
所用的时间。
因此通过它可以让游戏对象按照一个常速进行旋转,而不是依赖于它的帧频:
functionUpdate()
{
tranform.Rotate(0,5*Time.deltaTime,0);
}
同样地移动效果:
functionUpdate()
{
transform.Translate(0,0,2*Time.deltaTime);
}
如果想要一个值根据每帧的变化而变化(增加或减少),你应该使用Time.deltaTime来
乘以这个值。
这样才能使得变化的效果依赖于单位时间,而不是帧频。
这不仅使得游戏的运
行独立于帧频,也使得运动的效果符合现实。
同理,要让灯光的照射范围在每秒使半径增加2个单位,可进行如下编码:
functionUpdate()
{
light.range+=2.0*Time.deltaTime;
}
但是在通过force来处理rigidbody时,一般情况下不要乘以Time.deltaTime,因为Unity
引擎已经为你进行了处理。
第四章访问组件
组件被用来附加到游戏对象。
当附加一个渲染器组件(Renderer)时,将使得游戏对象
被渲染到屏幕上;当附加一个摄像机组件(Camera)时,将使得游戏对象变为摄像机对象。
所有的脚本都是组件,因此它们可以被附加到游戏对象中。
常用的组件都可以通过一个简单的成员变量来进行访问:
组件用于访问相应组件的成员变量
Transformtransform
Rigidbodyrigidbody
Rendererrenderer
Cameracamera(只能用于摄像机对象)
Lightlight(只能用于灯光对象)
Animationanimation
Collidercollider
如果游戏对象没有你想要获取的组件类型,上面的变量将被设置为null。
另外,也可以通过GetComponent函数来获取被附加到游戏对象中的任意内置组件或脚
本。
例如:
transfrom.Translate(0,1,0);
//等同于
GetComponent(Transfrom).Translate(0,1,0);
两者之间不同在于前者(transform等)是一个变量,而后者(Transform等)是一个类
或脚本名。
现在我们进行一个练习,以便更加深入地掌握GetComponent函数。
这个游戏对象附加
了两个脚本,我们在其中一个脚本中通过GetComponent函数来获取另一个脚本(叫做
OtherScript),并访问它的DoSomething函数:
functionUpdate()
{
//在当前游戏对象中查找名为OtherScript的脚本,并调用它的DoSomething函数。
otherScript=GetComponent(OtherScript);
otherScript.DoSomething();
}
第五章访问游戏对象
大多数高级的游戏代码都不只是操作单个游戏对象。
Unity脚本接口拥有多种方式来查
找和访问其他游戏对象或其中的组件。
假设有一个名为OtherScript的脚本被附加到游戏对
象中,该脚本包含了如下的代码片段:
varfoo=5;
functionDoSomething(param:
String)
{
print(param+"withfoo:
"+foo);
}
1、通过检查器进行访问
你可以通过检查器来为任意对象类型的变量分配值:
//需要将Translate拖拽到target变量上
vartarget:
Transform;
functionUpdate()
{
target.Translate(0,1,0);
}
你也可以把指向其他对象的引用暴露在检查器中。
例如:
你可以拖拽一个附加了
OtherScript脚本的游戏对象到检查器中的target变量中:
//可以在检查器中通过target变量来设置foo变量
vartarget:
OtherScript;
functionUpdate()
{
//设置foo变量
target.foo=2;
//调用DoSomething函数
target.DoSomething("Hello");
}
2、通过对象层次进行访问
你可以通过一个游戏对象中的Transform组件来查找该对象的子对象和父对象:
//查找游戏对象中名为“Hand”的子对象
//我们将该脚本附加到当前游戏对象中
transform.Find("Hand").Translate(0,1,0);
一旦找到了层次中的transform对象,你就可以通过使用GetComponent函数来获取其
他脚本:
//查找名为“Hand”的子对象,获取其中附加的OtherScript脚本,并设置foo变量为2。
transform.Find("Hand").GetComponent(OtherScript).foo=2;
//查找名为“Hand”的子对象,获取其中附加的OtherScript脚本,并调用DoSomething函数
transform.Find("Hand").GetComponent(OtherScript).DoSomething("Hello");
//查找名为“Hand”的子对象,获取其中附加的rigidbody对象,并申请一个force。
transform.Find("Hand").rigidbody.AddForce(0,10,0);
使用相同的原理,可以通过如下的代码来循环访问所有的子对象:
//将所有子对象都向上移动10个单位
for(varchild:
Transformintransform)
{
child.Translate(0,1,0);
}
3、通过名称或Tag进行访问
可以通过特定的Tag来调用GameObject.FindWithTag或
GameObject.FindGameObjectsWithTag函数,从而在所有的游戏对象中查找想要的游戏对象。
也可以通过游戏对象的名称来调用GameObject.Find函数来进行查找。
functionStart()
{
//通过名称查找
vargo=GameObject.Find("SomeGuy");
go.transform.Translate(0,1,0);
//通过tag查找
varplayer=GameObject.FindWithTag("Player");
player.transform.Translate(0,1,0);
}
在查找到的游戏对象上调用GetComponent函数,可以获取该游戏对象中所附加的内置
组件或脚本:
functionStart()
{
//通过名称查找
vargo=GameObject.Find("SomeGuy");
go.GetComponent(OtherScript).DoSomething();
//通过tag查找
varplayer=GameObject.FindWithTag("Player");
player.GetComponent(OtherScript).DoSomething();
}
一些特殊的对象都拥有一个访问自己的快捷方式,例如:
可以通过Camera.main变量来
代表主摄像机。
4、传递参数
一些事件消息都包含了详细的信息,例如:
触发器事件会把碰撞对象的碰撞器组件
(Collider)传递给事件处理器函数。
OnTriggerStay函数提供了指向一个碰撞器对象的引用,通过它我们可以获取其中附加的
rigidbody:
functionOnTriggerStay(other:
Collider)
{
//如果other碰撞器对象拥有rigidbody,就申请一个force。
if(other.rigidbody)
{
other.rigidbody.AddForce(0,2,0);
}
}
使用相同的原理,也可以获取碰撞器游戏对象中附加的内置组件或脚本:
functionOnTriggerStay(other:
Collider)
{
//如果other碰撞器对象拥有OtherScript脚本,就调用它的DoSomething函数。
//大多数情况下,碰撞器都不会附加脚本。
因此,我们需要先进行检查,以避免null引用异常。
if(other.GetComponent(OtherScript))
{
other.GetComponent(OtherScript).DoSomething();
}
}
5、查找同类型脚本的所有对象
通过类名或脚本名调用Object.FindObjectOfType或Object.FindObjectsOfType函数,可以
在场景中的所有游戏对象中获取一个或多个同类型的类对象或脚本对象:
functionStart()
{
//场景中查找附加了OtherScript脚本的任意一个游戏对象
varother:
OtherScript=FindObjectOfType(OtherScript);
other.DoSomething();
}
第六章向量
Unity使用Vector3类来表示所有的3D向量,可以通过x、y和z成员变量来访问一个
3D向量对象的各个组件:
varaPosition:
Vector3;
aPosition.x=1;
aPosition.y=1;
aPosition.z=1;
也可以使用Vector3的构造函数来一次性初始化所有的组件:
varaPosition=Vector3(1,1,1);
Vector3也定义了一些常量,用来表示常用的3D向量对象:
//等同于Vector3(0,1,0);
vardirection=Vector3.up;
可以通过如下代码片段,来访问单个3D向量对象:
someVector.Normalize();
可以通过如下代码片段,来访问多个3D向量对象:
theDistance=Vector3.Distance(oneVector,otherVector);
注:
Distance函数为类函数,所以在调用时必须在前面加上Vector3.。
也可以在多个3D向量对象之间使用常用的数学操作符:
combined=vector1+vector2;
第七章成员变量和全局变量
在函数外面定义的变量叫做成员变量,它们能够通过Unity的检查器进行访问,存储在
成员变量中的值将自动地保__________存在项目中。
varmemeberVariable=0.0;
上面的变量将作为一个叫做“MemeberVariable”的数字属性出现在检查器中。
如果设置变量的类型为组件类型(Transform、Rigidbody、Collider和脚本名等),可以通
过把游戏对象拖拽到检查器中这种类型的变量上来设置它们。
varenemy:
Transform;
functionUpdate()
{
if(Vecter3.Distance(enemy.postion,transform.position)<10)
{
print("Isensetheenemyisnear!
");
}
}
你也可以创建私有成员变量,它们主要用来存储状态信息,而且在脚本外具有不可见性。
私有成员变量不保存在磁盘上,也不能在检查器中进行编辑。
只有在检查器被设置为调试模
式时,才允许你通过修改私有成员变量来实时地更新调试器。
privatevarlastCollider:
Collider;
functionOnCollisionEnter(collisionInfo:
Collision)
{
lastCollider=collisionInfo.other;
}
使用static关键字进行声明的变量叫做全局变量,例如:
//一个名为“TheScriptName”的脚本中拥有一个someGlobal静态变量
staticvarsomeGlobal=5;
//你可以在脚本中像使用普通变量一样来使用它
print(someGlobal);
someGlobal=1;
为了能在其他脚本中访问全局变量,需要加上“TheScriptName.”前缀:
print(TheScriptName.someGlobal);
TheScriptName.someGlobal=10;
第八章实例化
实例化表示复制一个对象,包括所有附加的脚本和整个层次结构。
它并不理会指向克隆
层次结构外的对象的引用,而指向克隆层次结构内的对象的引用将会被映射到克隆的对象
上。
下面的脚本被附加到一个具有碰撞器的rigidbody上,当发生碰撞时,将摧毁本身并替
代为大量的爆炸物对象:
varexplosion:
Transform;
//当碰撞发生时,将摧毁自身并产生大量的预置爆炸物对象。
functionOnCollisionEnter()
{
Destroy(gameObject);
vartheClonedExplosion:
Transform;
theClonedExplosion=Instantiate(explosion,transform.position,transform.rotation);
}
实例化通常用于与预置对象(Prefabs)进行交互。
第九章协同程序和让步
在编写游戏代码时,通常需要在脚本中结束一系列的事件。
例如:
privatevarstate=0;
functionUpdate()
{
if(state==0)
{
//dostep0
state=1;
return;
}
if(state==1)
{
//dostep1
state=2;
return;
}
...
}
这时,我们使用让步(yield)语句是非常方便的,yield语句是一种特殊的return语句。
它确保函数在下次被调用时,能够从yield语句开始继续执行。
while(true)
{
//dostep0
//waitforoneframe
yield;
//dostep1
//waitforoneframe
yield;
...
}
你也可以传递一个特定的值给yield语句来推迟Update函数的执行,直到某个事件发生:
//dosomething
//waitfor5seconds
yieldWaitForSeconds(5.0);
//dosomethingmore...
你可以堆积并连接一些协同程序(Coroutine)。
例如,下面的示例在执行Do函数时,
立即执行随后的代码:
Do();
print("Thisisprintedimmediately");
functionDo()
{
print("Donow");
yieldWaitForSeconds
(2);
print("Do2secondslater");
}
下面的示例在执行完Do函数后,才执行随后的代码:
//chainthecoroutine
yieldStartCoroutine("Do");
print("Alsoafter2seconds");
print("ThisisaftertheDocoroutinehasfinishedexecution");
functionDo()
{
print("Donow");
yieldWaitForSeconds
(2);
print("Do2secondslater");
}
注:
不能在Update或FixedUpdate函数中使用yield语句,但可以在它们中使用
StartCoroutine函数来调用一个函数。
第十章使用C#编写脚本
在Unity中可以使用JavaScript、C#和Boo来编写脚本。
在使用C#编写脚本时,需注意
以下几个特点:
1、所有脚本都继承至MonoBehaviour
所有的行为脚本都必须直接地或间接地继承至MonoBehaviour。
在使用JavaScript时,
这种继承关系将自动生成,但在使用C#编写脚本时,必须显式地进行定义。
通过模板创建
的C#脚本时(Asset->Create->CSharpScript),自动生成的代码已经包含了这样的定义:
//C#
publicclassNewBehaviourScript:
MonoBehaviour
{
...
}
2、使用Awake或Start方法来进行初始化
在使用JavaScript时,所有在函数外的代码,在使用C#时,都必须把它们放置在Awake
或Start方法中。
Awake和Start方法的不同点在于:
前者在场景进行加载时被调用;后者在调用Update
或FixedUpdate方法之前被调用。
因此,Awake方法在Start方法之前被调用。
3、类名必须与文件名相同
在JavaScript中,类名被隐式地设置为文件名。
但在C#中,必须手动地进行设置。
4、在C#中,协同程序的使用语法与JavaScript不同。
协同程序必须返回一个IEnumerator类型,并且使用yieldreturn...来代替JavaScript中
的yield...。
usingSystem.Collections;
usingUnityEngine;
publicclassNewBehaviourScript:
MonoBehaviour
{
//C#coroutine
IEnumeratorSomeCoroutine()
{
//Waitforoneframe
yieldreturn0;
}
//Waitfortwoseconds
yieldreturnnewWaitForSeconds
(2);
}
5、不能使用命名空间(Namespace)
当前的Unity不支持把脚本放到一个命名空间中。
这可能在将来的版本中所有改变。
6、只有成员变量才能被序列化并显示在检查器中
私有和保护成员变量仅仅在专家模式(ExpertMode)下才显示在检查器中。
属性不能被
序列化并显示在检查器中。
7、避免使用构造器
永远不要使用构造器来初始化值,而应该在Awake或Start中进行,到时Unity会自动
触发相应的构造器,即使在编辑模式(EditMode)修改成员变量的值,也会自动触发。
这
通常在脚本编译完成后直接发生,以便为它们设置默认值。
这样设计的主要原因有两个:
构
造器的调用不可预期;构造器的调用可能为了预置的或未活动的游戏对象。
例如:
单例模式(SingletonPattern)对象使用构造器进行初始化时,可能会导致值为空
__________的严重后果。
因此,应该在Awake方法中来初始化单例模式对象。
请记住:
任何继承至
MonoBehaviour的类中,都不能包含使用构造器的代码。
第十一章重要类
1、在JavaScript或基于C#的类中,可访问的全局函数:
2、对游戏对象进行移动或旋转:
3、动画系统:
4、Rigidbodies:
5、FPSorThirdpersoncharactercontroller: