Version: 6000.3
语言: 中文
游戏对象基础知识
变换

GameObject 类

切换到脚本

Unity 的 GameObject 类表示可以存在于场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表
.游戏对象是 Unity 中场景的构建块,充当功能组件的容器,这些组件决定了游戏对象的外观及其作用。

GameObject 类类提供了一系列方法,允许您在代码中使用游戏对象。其中包括用于在游戏对象之间查找、建立连接和发送消息、添加或删除附加到游戏对象的组件以及设置与其在场景中的状态相关的值的方法。

有关 GameObject 类的每个成员的完整参考,请参阅 GameObject 脚本参考

有关在 Unity 编辑器的场景和层次结构中使用游戏对象的信息,请参阅游戏对象简介

场景状态属性

所有游戏对象在检查器一个 Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。更多信息
请参阅术语表
与游戏对象在场景中的状态相关,这些可以通过游戏对象的脚本 API 进行控制。

在检查器中查看的典型游戏对象。在本例中,定向光源。场景状态属性以红色轮廓显示。
在检查器中查看的典型游戏对象。在本例中,定向光源。场景状态属性以红色轮廓显示。

活动状态

游戏对象的活动状态
游戏对象的活动状态

游戏对象默认处于活动状态,但可以停用,这会关闭附加到游戏对象的所有组件。这通常意味着它将变得不可见,并且不会收到任何正常的回调或事件,例如UpdateFixedUpdate.

游戏对象的活动状态由游戏对象名称左侧的复选框表示。您可以使用以下命令来控制它GameObject.SetActive.

您还可以使用GameObject.activeSelf读取游戏对象的当前活动状态。用GameObject.activeInHierarchy读取游戏对象在场景中是否实际处于活动状态。GameObject.activeInHierarchy是必要的,因为游戏对象是否实际处于活动状态取决于其自身的活动状态及其所有父级的活动状态。如果它的任何父级不处于活动状态,那么尽管它有自己的活动设置,但它也不是活动状态。

静态状态

游戏对象的静态状态
游戏对象的静态状态

Unity 的一些系统,例如全局光照 一组对直接和间接光照进行建模以提供逼真的光照结果的技术。
请参阅术语表
、遮挡、批处理、导航和反射探针(Reflection Probes一个渲染组件,可捕获周围环境的各个方向的球形视图,就像摄像机一样。然后,捕获的图像将存储为立方体贴图,可供具有反射材质的对象使用。更多信息
请参阅术语表
,依赖于游戏对象的静态状态。您可以使用以下命令来控制哪些 Unity 系统将游戏对象视为静态GameObjectUtility.SetStaticEditorFlags.有关详细信息,请参阅静态游戏对象

标签和图层

游戏对象的 Tag 和 Layer 字段
游戏对象的 Tag 和 Layer 字段

标记提供了一种在场景中标记和识别游戏对象类型的方法,提供了一种类似但不同的方式,用于在某些内置作(例如渲染物理碰撞)中包含或排除游戏对象组。

有关如何在编辑器中使用标签和图层的更多信息,请参阅主用户手册页面标签可以分配给一个或多个游戏对象的引用词,以帮助您识别游戏对象以进行脚本编写。例如,你可以为玩家可以在游戏中吃的任何物品定义和“可食用”标签。更多信息
请参阅术语表
层Unity中的层可用于有选择地选择游戏对象组加入或退出某些进程或计算。这包括相机渲染、光照、物理碰撞或您自己的代码中的自定义计算。更多信息
请参阅术语表
.

您可以通过脚本修改标签和图层值,使用GameObject.tagGameObject.layer性能。您还可以使用CompareTag方法,包括验证标记是否存在,并且不会导致任何内存分配。

添加和删除组件

您可以在运行时添加或删除组件,这对于按程序创建游戏对象或修改游戏对象的行为方式非常有用。请注意,您还可以enabledisable脚本组件,以及某些类型的内置组件,通过脚本而不销毁它们。

在运行时添加组件的最佳方法是使用AddComponent<Type>,指定尖括号内的元件类型,如图所示。要删除组件,您必须使用Object.Destroy方法。

访问组件

最简单的情况是,游戏对象上的脚本需要访问附加到同一游戏对象的另一个组件(请记住,附加到游戏对象的其他脚本也是组件本身)。为此,第一步是获取对要使用的组件实例的引用。这是使用 GetComponent 方法完成的。通常,您希望将 Component 对象分配给变量,这是使用以下代码完成的。在此示例中,脚本获取对刚体允许游戏对象受到模拟重力和其他力影响的组件。更多信息
请参阅术语表
组件:

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

一旦你有了对组件实例的引用,你就可以像在检查器中一样设置其属性的值:

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

    // Change the mass of the object's Rigidbody.
    rb.mass = 10f;
}

您还可以调用组件引用上的方法,例如:

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

    // Add a force to the Rigidbody.
    rb.AddForce(Vector3.up * 10f);
}

注意:您可以有多个自定义脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间修改组件属性以及以您喜欢的任何方式响应用户输入。更多信息
请参阅术语表
附加到同一个游戏对象。如果您需要从另一个脚本访问一个脚本,您可以像往常一样使用 GetComponent,只需使用脚本类的名称(或文件名)来指定所需的组件类型。

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

访问其他游戏对象上的组件

尽管它们有时是孤立运行的,但脚本通常会跟踪其他游戏对象,或者更常见的是跟踪其他游戏对象上的组件。例如,在烹饪游戏中,厨师可能需要知道炉子的位置。Unity 提供了不同的方法来检索其他对象,每种方法都适用于某些情况。

使用检查器中的变量链接到游戏对象

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

public class Chef : MonoBehaviour
{
    public GameObject stove;

    // Other variables and functions...
}

此变量将在 Inspector 中作为 GameObject 字段可见。

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

将预制件从“项目”窗口拖到“检查器”窗口中的“游戏对象”字段中
将预制件从“项目”窗口拖到“检查器”窗口中的“游戏对象”字段中

GetComponent 函数和 Component 访问变量可用于此对象,就像其他对象一样,因此您可以使用如下代码:

public class Chef : MonoBehaviour {

    public GameObject stove;

    void Start() {
        // Start the chef 2 units in front of the stove.
        transform.position = stove.transform.position + Vector3.forward * 2f;
    }
}

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

public Transform playerTransform;

当您处理具有永久连接的单个对象时,将对象与变量链接在一起最有用。您可以使用数组变量链接多个相同类型的对象,但仍必须在 Unity 编辑器中而不是在运行时建立连接。在运行时定位对象通常很方便,Unity 提供了两种基本方法来执行此作,如下所述。

查找子游戏对象

有时,游戏场景会使用多个相同类型的游戏对象,例如收藏品、航路点和障碍物。这些可能需要由监督或对它们做出反应的特定脚本进行跟踪(例如,所有航路点可能需要可供寻路脚本使用)。使用变量来链接这些游戏对象是可能的,但如果必须将每个新航点拖到脚本上的变量上,则设计过程会变得乏味。同样,如果删除了航点,则必须删除对丢失的游戏对象的变量引用,这是一件很麻烦的事情。在这种情况下,通常最好通过使一组游戏对象都成为一个父游戏对象的子级来管理它们。可以使用父游戏对象的变换组件变换组件确定场景中每个对象的位置、旋转和缩放。每个游戏对象都有一个 Transform。更多信息
请参阅术语表
(因为所有游戏对象都隐式具有 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");

当游戏对象具有可以在游戏过程中添加和删除的子游戏对象时,这非常有用。在游戏过程中可以拿起和放下的工具或器具就是一个很好的例子。

发送和广播消息

在编辑项目时,您可以在 Inspector 中设置游戏对象之间的引用。但是,有时无法提前设置这些(例如,在游戏中查找离角色最近的项目,或引用在加载场景后实例化的游戏对象)。在这些情况下,您可以在运行时查找引用并在游戏对象之间发送消息。

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

SendMessage更具体一些,并且仅将调用发送到 GameObject 本身的命名方法,而不是其子项。

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

按名称或标签查找游戏对象

只要有一些信息可以识别游戏对象,就可以在场景层次结构中的任何位置找到游戏对象。可以使用 GameObject.Find 函数按名称检索单个对象:

GameObject player;

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

还可以使用 GameObject.FindWithTagGameObject.FindGameObjectsWithTag 方法通过其标记定位对象或对象集合。

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

GameObject chef;
GameObject[] stoves;

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

创建和销毁游戏对象

可以在项目运行时创建和销毁游戏对象。在 Unity 中,可以使用 Instantiate 方法创建游戏对象,该方法创建现有对象的新副本。

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

Destroy 方法在帧更新完成后销毁对象,或者(可选)在短时间延迟后销毁对象:

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

请注意,Destroy 函数可以销毁单个组件,而不会影响游戏对象本身。一个常见的错误是将this并假设它销毁了脚本附加到的游戏对象:

Destroy(this);

this表示脚本,而不是游戏对象。它实际上只会销毁调用它的脚本组件,并保持游戏对象不变,但删除了脚本组件。

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

要创建 Unity 内置基元的实例,请使用 GameObject.CreatePrimitive,它实例化您指定类型的基元。可用的基元类型包括 SphereCapsuleCylinderCubePlane四边形一种类似于平面但其边只有一个单位长的基元对象,它仅使用 4 个顶点,并且表面定向在局部坐标空间的 XY 平面上。更多信息
请参阅术语表
.

Unity 游戏对象菜单中可用的基元形状
Unity 的游戏对象菜单中可用的基元形状

其他资源

游戏对象基础知识
变换