• 使用组件控制游戏对象
    • 访问组件
    • 访问其他对象
      • 用变量连接对象
      • 查找子对象
      • 按照名称或标签查找对象

    使用组件控制游戏对象

    在 Unity 编辑器中,你可以使用检视视图修改组件的属性。例如,改变游戏对象的变换组件的位置值,将会导致游戏对象的位置发生变化。类似地,修改渲染器材质的颜色或刚体的质量,将会对象的外观或行为产生相应的影响。大多数情况下,脚本也可以修改组件属性,从而操纵游戏对象。不同的是,脚本可以随时间改变属性的值,或响应用户的输入。通过在正确的时间修改、创建和销毁对象,可以实现任何类型的游戏。

    访问组件

    最简单也最常见的情况是,脚本需要访问游戏对象上绑定的其他组件。正如简介部分所述,组件实际上是某个类的实例,所以第一步是拿到要访问的组件实例的引用。这一步通过 GetComponent 函数完成。通常,你需要把组件实例分配给一个变量。在 C# 中使用下面的语法完成:

    1. void Start () {
    2. Rigidbody rb = GetComponent<Rigidbody>();
    3. }

    在 UnityScript 中,语法稍有不同:

    1. function Start () {
    2. var rb = GetComponent.<Rigidbody>();
    3. }

    一旦有了组件实例的引用,就可以像在检视视图 Inspector 中一样,设置它的属性值:

    1. void Start () {
    2. Rigidbody rb = GetComponent<Rigidbody>();
    3. // Change the mass of the object's Rigidbody.
    4. rb.mass = 10f;
    5. }

    一个额外特性是,脚本可以调用组件实例的函数,这在检视视图中是不可能的:

    1. void Start () {
    2. Rigidbody rb = GetComponent<Rigidbody>();
    3. // Add a force to the Rigidbody.
    4. rb.AddForce(Vector3.up * 10f);
    5. }

    还需要注意到,同一个游戏对象没有理由不能绑定多个自定义脚本。如果需要从一个脚本访问另一个脚本,可以像平常一样使用 GetComponent,只需要用脚本类的名字(或文件名)指定所需的组件类型。

    如果尝试检索一个实际上尚未添加到游戏对象的组件,GetComponent 函数将返回 null;如果尝试在一个 null 对象上改变任意值,会在运行时抛出一个空指针错误。

    访问其他对象

    尽管脚本有时是孤立地运行,但是脚本跟踪其他对象的状态也很常见。例如,一个追击的敌人可能需要知道被追击玩家的位置。Unity 提供了许多不同的方式来检索其他对象,每种方式对应特定的情况。

    用变量连接对象

    查找关联对象的最直接方式是,为脚本添加一个公共的游戏对象变量:

    1. public class Enemy : MonoBehaviour {
    2. public GameObject player;
    3. // Other variables and functions...
    4. }

    这个变量将像其他变量一样显示在检视视图 Inspector 中。

    使用组件控制游戏对象 - 图1

    现在,可以从场景视图或层级视图拖动一个对象到这个变量上进行分配。然后,就可以访问这个对象的 GetComponent 函数和组件变量。因此,你可以使用下面的代码:

    1. public class Enemy : MonoBehaviour {
    2. public GameObject player;
    3. void Start() {
    4. // Start the enemy ten units behind the player character.
    5. transform.position = player.transform.position - Vector3.forward * 10f;
    6. }
    7. }

    另外,如果在脚本中声明了某个组件类型的公共变量,你可以拖动绑定了该组件的任意对象到该变量上。这时将直接访问组件,而不是游戏对象。

    1. public Transform playerTransform;

    当处理永久链接的独立对象时,用变量连接对象是最合适的方式。你可以用一个数组变量来连接多个同类型的对象,但是这种连接必须在 Unity 编辑器中建立,而不是在运行时。不过,在运行时定位对象也很方便,Unity 提供了两种基本方式来实现这点。

    查找子对象

    有时,一个游戏场景将使用多个相同类型的对象,例如敌人、路径和障碍物。可能需要一个特定脚本来跟踪、监督它们,或者还需要对它们进行响应(例如,用一个寻路脚本维护所有的路径)。虽然使用变量连接这些对象是一种可行的方式,但是如果每个新行路径都需要拖拽到某个脚本的变量上,将使设计过程变得非常乏味。同样,如果一个路径被删除,那么移除变量对无效对象的引用就会变成麻烦。在这样的情况下,通常最好是把它们都作为子对象放到一个父对象中,用一个对象集合来管理它们。子对象可以通过父对象的变换组件 Transform 来检索(因为所有游戏对象都隐含一个变换组件):

    1. using UnityEngine;
    2. public class WaypointManager : MonoBehaviour {
    3. public Transform[] waypoints;
    4. void Start() {
    5. waypoints = new Transform[transform.childCount];
    6. int i = 0;
    7. foreach (Transform t in transform) {
    8. waypoints[i++] = t;
    9. }
    10. }
    11. }

    你还可以使用 Transform.Find 函数查找特定名称的子对象:

    1. transform.Find("Gun");

    在游戏过程中,如果父对象的子对象可以被添加和删除,这种方式可能很有用。一个很好的例子是,一把武器可以被捡起和放下。

    按照名称或标签查找对象

    只要场景中的游戏对象具有某些标识信息,那么,总是可以定位任意位置的游戏对象。可以用 GameObject.Find 函数按照名称检索单个对象:

    1. GameObject player;
    2. void Start() {
    3. player = GameObject.Find("MainHeroCharacter");
    4. }

    也可以使用 GameObject.FindWithTag 和 GameObject.FindGameObjectsWithTag 函数按照标签来定位对象或对象集合:

    1. GameObject player;
    2. GameObject[] enemies;
    3. void Start() {
    4. player = GameObject.FindWithTag("Player");
    5. enemies = GameObject.FindGameObjectsWithTag("Enemy");
    6. }