Version: 2022.1
重要的类
重要的类 - MonoBehaviour

重要的类 - GameObject

Unity’s GameObject class represents anything which can exist in a Scene.

此页面涉及使用 Unity GameObject 类进行的脚本编写。若要了解如何在 Unity 编辑器的场景和层级视图中使用 GameObject,请参阅用户手册的 GameObject 部分。有关 GameObject 类的每个成员的详尽参考,请参阅 GameObject 脚本参考

GameObject 是 Unity 中场景的构建块,可充当用于确定 GameObject 外观以及 GameObject 作用的功能组件的容器。

In scripting, the GameObject class provides a collection of methods which allow you to work with them in your code, including finding, making connections and sending messages between GameObjects, and adding or removing components attached to the GameObject, and setting values relating to their status within the scene.

场景状态属性

You can use scripts to modify many properties related to a GameObject’s status in the scene. These typically correspond to the controls visible near the top of the inspector when you have a GameObject selected in the Editor.

它们不与任何特定组件相关,会显示在 GameObject 的 Inspector 顶部(组件列表上方)。

在 Inspector 中查看的典型 GameObject。在此例中是方向光。场景状态属性具有红色轮廓。
在 Inspector 中查看的典型 GameObject。在此例中是方向光。场景状态属性具有红色轮廓。

所有 GameObject 都在 Inspector 顶部共享一组与场景中 GameObject 状态相关的控件,这些控件可以通过 GameObject 的脚本 API 进行控制。

如果要快速列出 GameObject 类的所有可用 API,请参阅 GameObject 脚本参考

活动状态

GameObject 的活动状态
GameObject 的活动状态

GameObject 在默认情况下处于活动状态,但可以停用,这会关闭附加到 GameObject 的所有组件。这通常意味着它将变得不可见,不会接收任何正常回调或事件,例如 UpdateFixedUpdate

GameObject 的活动状态由 GameObject 名称左侧的复选框表示。可以使用 GameObject.SetActive 控制此状态。

You can also use GameObject.activeSelf to read the current active state of a GameObject. Use GameObject.activeInHierarchy to read whether the GameObject is actually active in the scene. GameObject.activeInHierarchy is necessary because whether a GameObject is actually active is determined by its own active state and the active state of all of its parents. If any of its parents aren’t active, then it’s not active despite its own active setting.

静态状态

GameObject 的静态状态
GameObject 的静态状态

Unity 的一些系统(如全局光照、遮挡、批处理、导航和反射探针)依赖于 GameObject 的静态状态。可以使用 GameObjectUtility.SetStaticEditorFlags 控制哪些 Unity 系统将 GameObject 视为静态。有关详细信息,请阅读此处的静态 GameObject

标签和层

The Tag and Layer fields of a GameObject
The Tag and Layer fields of a GameObject

标签 (Tag)提供一种在场景中标记和识别 GameObject 类型的方式,而层 (Layer)提供一种类似但不同的方式在某些内置操作(例如渲染物理碰撞)中包括或排除 GameObject 组。

有关如何在编辑器中使用标签和层的更多信息,请参阅关于标签的主要用户手册页面。

You can modify tag and layer values via script using the GameObject.tag and GameObject.layer properties. You can also check a GameObject’s tag efficiently by using the CompareTag method, which includes validation of whether the tag exists, and doesn’t cause any memory allocation.

添加和移除组件

可以在运行时添加或移除组件,这对于以程序化方式创建 GameObject 或修改 GameObject 行为方式可能非常有用。请注意,还可以通过脚本启用或禁用脚本组件和某些类型的内置组件,而不销毁它们。

在运行时添加组件的最佳方法是使用 AddComponent<Type>(在显示的尖括号中指定组件类型)。若要移除组件,必须对组件本身使用 Object.Destroy 方法。

访问组件

最简单的情况是 GameObject 上的脚本需要访问附加到同一个 GameObject 的另一个组件(请记住,附加到 GameObject 的其他脚本本身也是组件)。为此,第一步是获取对要使用的组件实例的引用。这通过 GetComponent 方法来完成。通常要将组件对象分配给变量,而此操作使用以下代码实现。在此示例中,脚本获取对同一个 GameObject 上的 Rigidbody 组件的引用:

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();
}

获得对组件实例的引用后,可以像在 Inspector 中一样设置其属性的值:

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    // 更改对象的刚体质量。
    rb.mass = 10f;
}

还可以对组件引用调用方法,例如:

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    // 向刚体添加作用力。
    rb.AddForce(Vector3.up * 10f);
}

注意:可以将多个自定义脚本附加到同一个 GameObject。如果需要从一个脚本访问另一个脚本,可以像往常一样使用 GetComponent,只需使用脚本类的名称(或文件名)来指定所需的组件类型。

如果尝试检索尚未实际添加到 GameObject 的组件类型,则 GetComponent 将返回 null;如果尝试更改 null 对象上的任何值,将在运行时出现 null 引用错误。

访问其他 GameObject 上的组件

Although they sometimes operate in isolation, it’s common for scripts to keep track of other GameObjects, or more commonly, components on other GameObjects. For example, in a cooking game, a chef might need to know the position of the stove. Unity provides a number of different ways to retrieve other objects, each appropriate to certain situations.

在 Inspector 中使用变量链接到 GameObject

查找相关游戏对象的最直接方法是向脚本添加公共的游戏对象变量:

public class Chef : MonoBehaviour
{
    public GameObject stove;

    // 其他变量和函数...
}

此变量在 Inspector 中会显示为 GameObject 字段

现在可以将对象从场景或 Hierarchy 面板拖到此变量上,对其进行分配。

将预制件从 Project 窗口拖动到 Inspector 窗口的 GameObject 字段中
将预制件从 Project 窗口拖动到 Inspector 窗口的 GameObject 字段中

GetComponent 函数和组件访问变量与其他任何变量一样可用于此对象,因此可以使用如下代码:

public class Chef : MonoBehaviour {

    public GameObject stove;

    void Start() {
        // 在 stove 前方 2 个单位处启动 chef。
        transform.position = stove.transform.position + Vector3.forward * 2f;
    }
}

此外,如果在脚本中声明组件类型的公共变量,则可以拖动已附加该组件的任何游戏对象。这样可以直接访问组件而不是游戏对象本身。

public Transform playerTransform; 

Linking objects together with variables is most useful when you are dealing with individual objects that have permanent connections. You can use an array variable to link several objects of the same type, but the connections must still be made in the Unity editor rather than at runtime. It’s often convenient to locate objects at runtime and Unity provides two basic ways to do this, as described below.

查找子 GameObject

Sometimes, a game Scene makes use of a number of GameObjects of the same type, such as collectibles, waypoints and obstacles. These might need to be tracked by a particular script that supervises or reacts to them (for example, all waypoints might need to be available to a pathfinding script). Using variables to link these GameObjects is a possibility but it makes the design process tedious if each new waypoint has to be dragged to a variable on a script. Likewise, if a waypoint is deleted, then it’s a nuisance to have to remove the variable reference to the missing GameObject. In cases like this, it is often better to manage a set of GameObjects by making them all children of one parent GameObject. The child GameObjects can be retrieved using the parent’s Transform component (because all GameObjects implicitly have a Transform):

using UnityEngine;

public class WaypointManager : MonoBehaviour {
    public Transform[] waypoints;

    void Start()
    {
        waypoints = new Transform[transform.childCount];
        int i = 0;

        foreach (Transform t in transform)
        {
            waypoints[i++] = t;
        }
    }
}

还可以使用 Transform.Find 方法按名称查找特定子对象: transform.Find("Frying Pan");

当 GameObject 具有可以在游戏运行过程中添加和移除的子 GameObject 时,这种功能可能很有用。可以在游戏运行过程中拾取和放下的工具或器皿就是这方面的一个很好例子。

发送和广播消息

While editing your project you can set up references between GameObjects in the Inspector. However, sometimes it’s impossible to set up these in advance (for example, finding the nearest item to a character in your game, or making references to GameObjects that were instantiated after the Scene loaded). In these cases, you can find references and send messages between GameObjects at runtime.

通过 BroadcastMessage 可以发送对命名方法的调用,而无需具体说明应实现该方法的位置。可以使用它对特定 GameObject 或其任何子项上的每个 MonoBehaviour 调用命名方法。可以选择强制要求必须至少有一个接收方(否则会生成错误)。

SendMessage 更具体一些,只对 GameObject 本身(而不对其子项)发送对命名方法的调用。

SendMessageUpwards 是类似方法,但是对 GameObject 及其所有_父项_ 发送对命名方法的调用。

按名称或标签查找 GameObject

It’s always possible to locate GameObjects anywhere in the Scene hierarchy as long as you have some information to identify them. Individual objects can be retrieved by name using the GameObject.Find function:

GameObject player;

void Start()
{
    player = GameObject.Find("MainHeroCharacter");
}

还可以使用 GameObject.FindWithTagGameObject.FindGameObjectsWithTag 方法按标签查找对象或者对象集合。

例如,在一个烹饪游戏中有一个厨师角色,厨房中有多个炉子(每个都标记为 “Stove”):

GameObject chef;
GameObject[] stoves;

void Start()
{
    chef = GameObject.FindWithTag("Chef");
    stoves = GameObject.FindGameObjectsWithTag("Stove");
}

创建和销毁 GameObject

可以在项目运行期间创建和销毁 GameObject。在 Unity 中,可以使用 Instantiate 方法创建 GameObject。该方法可以生成现有对象的新副本。

有关如何实例化 GameObject 的完整说明和示例,请参阅在运行时实例化预制件

The Destroy method destroys an object after the frame update has finished or optionally after a short time delay:

void OnCollisionEnter(Collision otherObj) {
    if (otherObj.gameObject.tag == "Garbage can") {
        Destroy(gameObject, 0.5f);
    }
}

Note that the Destroy function can destroy individual components and not affect the GameObject itself. A common mistake is to write this and assume it destroys the GameObject the script is attached to:

 Destroy(this);

this represents the script, and not the GameObject. It will actually just destroy the script component that calls it and leave the GameObject intact but with the script component removed.

原始对象

GameObject 类为 Unity GameObject 菜单中的可用选项提供了基于脚本的替代方案,可用于创建原始对象

若要创建 Unity 内置原始对象的实例,请使用 GameObject.CreatePrimitive,它会实例化所指定的类型的原始对象。可用的原始类型有 SphereCapsuleCylinderCubePlaneQuad

Unity GameObject 菜单中提供的原始形状
Unity GameObject 菜单中提供的原始形状
重要的类
重要的类 - MonoBehaviour