使用脚本

此处简单介绍如何在工程中创建和使用脚本。有关撰写 API 脚本的详细信息,请参阅 Scripting Reference | 脚本撰写组件手册。有关通过撰写脚本创建游戏的详细信息,请参阅本手册的创建游戏 (Creating Gameplay) 部分

Unity 中的行为脚本可使用 JavaScriptC#Boo 撰写。您也可在单个工程中使用这三种语言的任意组合,但是一种脚本采用其他脚本中定义的类时可能存在一些限制。

新建脚本

脚本文件不同于网格 (Meshes) 或 (Textures) 等其他资源,其可在 Unity 中创建。要新建脚本,请在主菜单中依次单击资源 (Assets)->创建 (Create)->JavaScript (或资源 (Assets)->创建 (Create)->C Sharp Script资源 (Assets)->创建 (Create)->Boo Script)。这将新建一个名为NewBehaviourScript的脚本,将其置于工程视图 (Project View) 中的所选文件夹下。如果没有在工程视图 (Project View) 中选择文件夹,将在根级别上创建脚本。

您可在工程视图 (Project View) 中双击此脚本进行编辑。这将按照 Unity 偏好设置启动默认文本编辑器。要设置默认脚本编辑器,请更改Unity->偏好设置 (Preferences)->外部脚本编辑器 (External Script editor) 中的下拉项。

以下是一个新建的空行为脚本示例:

function Update () {
} 

新建的空脚本本身没多少作用,所以需要我们添加一些功能。请按以下方式更改脚本内容:

function Update () {
    print("Hello World");
} 

执行脚本后,这段代码会在控制台中打印 "Hello World"。但现在还没有任何东西可触发代码的执行。必须将脚本附加到场景 (Scene) 中的活动游戏对象 (GameObject) 后才可执行脚本。

将脚本附加至对象

保存上述脚本,然后在场景 (Scene) 中选择游戏对象 (GameObject)->新建 (Create Other)->立方体 (Cube) 来新建对象。

现在,将脚本从工程视图 (Project View) 拖曳至立方体 (Cube)(位于场景 (Scene) 或层级视图 (Hierarchy View) 中都可以)。您也可选中立方体 (Cube),然后选择组件 (Component)->脚本 (Scripts)->新行为脚本 (New Behaviour Script)。任一方法都可将脚本附加至立方体 (Cube)。创建的每个脚本都将显示在组件 (Component)->脚本 (Scripts) 菜单中。

如果您选择立方体 (Cube),然后查看检视器 (Inspector),您会发现此脚本已显示出来。这表示脚本已附加至对象。

按下播放 (Play) 按钮测试创建效果。您可看见播放 (Play)/暂停 (Pause)/单步 (Step) 按钮旁边显示文本"Hello World"。请在看见此文本时退出播放模式。

操控游戏对象 (GameObject)

print()语句在调试脚本时可能非常有用,但脚本不可操纵附加至其本身的游戏对象 (GameObject)。让我们更改脚本添加一些功能:

function Update () {
    transform.Rotate(0, 5*Time.deltaTime, 0);
} 

如果您不大熟悉脚本,这些代码看起来头疼是很正常的。以下是一些需要理解的重要概念:

  1. function Update () {}是一个用来存放 Unity 每秒执行多次的代码的容器(每帧执行一次)。
  2. transform 是游戏对象 (GameObject) 变换组件 (Transform Component) 中的引用。
  3. Rotate()是变换 (Transform) 组件 (Component) 中包含的函数。
  4. 用逗号隔开的数字分别表示三维空间中的 X、Y、Z 轴的旋转角度。
  5. Time.deltaTime是 Time 类的一个成员,用来指示事件一秒内变化的量。无论你的机器一秒钟播放多少帧,立方体都会以相同的速度旋转。因此,5*Time.deltaTime 表示 5 度/秒。

了解这些概念后,我们能够理解这段代码为"每一帧,让此游戏对象 (GameObject) 的变换 (Transform) 组件旋转一个小角度,这样可保持这个对象沿着 Y 轴每秒旋转 5°"。

您可以按照我们访问变换的相同方式访问许多其他组件 (Components)。您必须使用组件 (Component) 菜单将组件 (Component) 添加至游戏对象 (GameObject)。您可直接访问的组件 (Components) 都列在游戏对象脚本组件手册页面 (GameObject Scripting Reference Page)变量 (Variables) 中。

更多有关游戏对象 (GameObjects)、脚本 (Scripts) 和组件 (Components) 之间关系的信息,请转至游戏对象 (GameObjects) 页面或本手册的使用组件 (Using Components) 页面。

变量的力量

到目前为止,我们的脚本始终保持让立方体 (Cube) 每秒旋转 5 度。我们可能需要改变立方体每秒旋转的度数。我们可以更改此数字并保存,但我们必须等待脚本被编译,还必须进入播放模式才可查看结果。这里有一种更快速的解决方法。我们可以在播放模式下实时试验旋转速度,这很容易做到。

我们将使用速度变量,并在函数中使用此变量,而非在 Rotate() 函数中键入5。将脚本更改为以下代码并保存:

var speed = 5.0;

function Update () {
    transform.Rotate(0, speed*Time.deltaTime, 0);
}

现在,选择立方体 (Cube) 并查看检视器 (Inspector)。注意看速度变量是如何显示的。

现在可直接在检视器 (Inspector) 中直接修改此变量。选中变量,按退格 (Return) 键修改值。您也可右键单击或在选项 (option) 上单击此值,并拖动鼠标向上或向下。您随时可更改变量,甚至包括游戏运行时。

点击播放 (Play) 并尝试修改速度值。立方体的 (Cube) 的旋转速度将立即发生改变。退出播放 (Play) 模式后,您会看到改变的值又恢复为您进入播放 (Play) 模式前的值。这样,您可播放、调整和试着查找最佳值,然后一直使用这个值。

在检视器 (Inspector) 中更改变量值的技术,可以让您轻松将一个脚本重复使用在多个对象上,每个对象都有不同的变量值。如果将脚本附加到多个立方体 (Cubes) 并更改每个立方体的速度,则所有立方体将以不同的速度旋转,即使它们使用的是相同的脚本。

访问其他组件

撰写脚本组件时,您可以访问脚本内游戏对象 (GameObject) 上的其他组件。

使用游戏对象 (GameObject) 成员

您可以直接访问游戏对象 (GameObject) 类中的任意成员。在这里,您将看见 游戏对象 (GameObject) 类所有成员的列表。如果将任何指定的类作为组件 (Component) 附加至游戏对象 (GameObject),只需在脚本中输入成员名称即可直接访问组件 (Component)。例如,输入 transform 等价于输入 gameObject.transform游戏对象是通过编译器来确认的,除非你专门引用一个不同的游戏对象 (GameObject)。

输入this 将可以访问您正在撰写的脚本组件 (Component)。输入 this.gameObject 将可以访问附加此脚本的游戏对象 (GameObject)。输入 gameObject 即可访问该游戏对象。从逻辑上来说,输入 this.transform 相当于输入 transform。如需访问非游戏对象 (GameObject) 成员的组件 (Component),则必须使用 gameObject.GetComponent(),对此我们将在下一页进行介绍。

有许多组件 (Components) 都可直接在任意脚本中访问。例如,如需访问变换 (Transform) 组件的 Translate 函数,您只需输入 transform.Translate()gameObject.transform.Translate()。此方法之所以有用,是因为所有脚本已附加至游戏对象 (GameObject)。输入 transform 时,则表示您将以隐性方式访问正在撰写其脚本的游戏对象 (GameObject) 的变换组件 (Transform Component)。明确一点,您需要输入 gameObject.transform。各种方法没有优劣之分,全由脚本撰写人员的喜好决定。

要了解您可以隐性方式访问的所有组件 (Components) 列表,请参阅脚本撰写组件手册 (Scripting Reference)游戏对象 (GameObject) 页面。

使用 GetComponent()

有许多组件 (Components) 未直接引用为游戏对象 (GameObject)类的成员。所以您无法以隐性方式访问它们,您必须以显性方式访问它们。为此,您可以调用 GetComponent("组件名称") 并将引用存储至结果。这在您需要引用附加至游戏对象 (GameObject) 的其他脚本时最为常见。

如果您正在输入 Script B 并需要引用已附加至同一游戏对象 (GameObject) 的Script A,您必须使用 GetComponent() 进行引用。在脚本 B (Script B) 中,您只需输入:

scriptA = GetComponent("ScriptA");

如需获取有关 GetComponent() 使用方法的更多帮助,请参阅GetComponent() 脚本组件手册 (Script Reference) 页面。

访问其他脚本组件 (Components) 中的变量

附加至您游戏对象 (GameObjects) 的所有脚本都是组件 (Components)。因此,您可在脚本中使用 GetComponent 方法访问公共变量(和方法)。例如:

function Start () {
   // Print the position of the transform component, for the gameObject this script is attached to
   Debug.Log(gameObject.GetComponent<Transform>.().position);
}

在之前的 GetComponent<T> 示例中,函数用于访问变换 (Transfor) 组件的位置属性。此方法也可用于访问自定义脚本组件中的变量:

(MyClass.js)
public var speed : float = 3.14159;

(MyOtherClass.js)
function Start () {
   // Print the speed variable from the MyClass script Component attached to the gameObject
   Debug.Log(gameObject.GetComponent<MyClass>.().speed);
}

访问 Javascript C# 中定义的变量

要在编译 Javascript 代码时访问 C# 脚本中定义的变量,则必须存在包含 C# 代码的已编译程序集 (Assembly)。Unity 在不同阶段执行编译,详情请参阅脚本组件手册 (Scripting Reference) 的脚本编译 (Script Compilation) 部分。如需创建使用 C# 脚本中的类或变量的 Javascript,只需将 C# 脚本放入 "标准资源 (Standard Assets)"、"专业版标准资源 (Pro Standard Assets)" 或 "插件 (Plugins)" 文件夹和这些文件夹外的 Javascript。系统将首先编译"标准资源 (Standard Assets)"、"专业版标准资源 (Pro Standard Assets)" 或 "插件 (Plugins)"中的代码,然后再编译这些文件夹外的代码,以便编译步骤(您的 C# 脚本)中定义的类型 (Types) 能够用于之后的编译步骤(您的 Javascript 脚本)。

一般而言,"标准资源 (Standard Assets)"、"专业版标准资源 (Pro Standard Assets)" 或 "插件 (Plugins)" 文件夹中的代码,无论使用何种语言(C#、Javascript 或 Boo),都将首先被编译,并且其结果可用于后续编译阶段的脚本中。

优化变量访问

在某些情况下,您可能会在代码或每帧中多次使用 GetComponent。每次调用 GetComponent 都需要在内部执行几个额外步骤才可获取所需的组件引用。有一个更有效的方法,例如,将引用存储至 Start() 函数中的组件。这样您既可存储引用也不会直接检索引用,这对于检查 null 引用也是一个好方法:

(MyClass.js)
public var speed : float = 3.14159;

(MyOtherClass.js)
private var myClass : MyClass;
function Start () {
   // Get a reference to the MyClass script Component attached to the gameObject
   myClass = gameObject.GetComponent<MyClass>.();
}
function Update () {
   // Verify that the reference is still valid and print the speed variable
   if(myClass != null)
      Debug.Log (myClass.speed);
}

静态变量

也可在您的类中定义静态变量。 这里将有一个且只有一个特定类的静态变量实例,您无需实例化类对象就可修改静态变量实例:

(MyClass.js)
static public var speed : float = 3.14159;

(MyOtherClass.js)
function Start () {
   Debug.Log (MyClass.speed);
}

建议不要在对象引用中使用静态变量,以确保未使用的对象能够从内存中删除。

下一步怎么走

这只是一个如何在编辑器中使用脚本的简短介绍,有关更多示例,请参阅 Unity 教程,教程可从我们的资源商店 (Asset Store) 免费获取。您也可通读脚本组件手册 (Script Reference) 中的 脚本概览 (Scripting Overview),它详细介绍了使用 Unity 撰写脚本的方法,并随附链接至更多详细信息的指针。如果您确实没弄明白,请务必访问 Unity 问答 (Unity Answers)Unity 论坛 (Unity Forums) 并在这里提问。您将在此找到满意答案。

Page last updated: 2013-06-14