Unity 的GameObject类表示能够存在于场景场景包含了你的游戏环境和菜单。你可以将每个独特的场景文件视为一个独特的关卡。在每个场景中,你都放置你的环境、障碍物和装饰,实际上就是分块设计和构建你的游戏。 详细信息
参见 词汇表中的任何事物。GameObjects 是 Unity 中用于构造场景的构建模块,并用作功能性组件的容器,而功能性组件决定着 GameObject 的外观和用途。
GameObject 类类提供了一组方法,让你能够在你的代码中使用 GameObjects。这些方法包括查找、建立连接以及发送 GameObjects 之间的消息、添加或移除附加到 GameObject 上的组件以及设定与其在场景中的状态相关的值。
有关 GameObject 类的每个成员的完整引用信息,请参阅GameObject 脚本引用。
有关在 Unity 编辑器中的场景和层级结构中使用 GameObjects 的信息,请参阅GameObject 简介。
所有 GameObjects 在检查器Unity 的一个窗口,显示有关当前所选 GameObject、道具或项目设置的信息,让你能够检查和编辑值。 详细信息
参见 词汇表顶部共享一组与 GameObject 在场景中的状态相关的控件,且这些控件可通过 GameObject 的脚本编写 API 控制。
默认情况下,GameObjects 处于活动状态,但可以停用,这将关闭附加到 GameObject 上的所有组件。这意味着它在通常情况下将变得不可见,并且不会收到任何常规回调或事件,如 Update
或 FixedUpdate
。
GameObject 的活动状态由 GameObject 名称左侧的复选框表示。你可以使用 GameObject.SetActive
控制该状态。
您还可以使用 GameObject.activeSelf
来读取 GameObject 的当前活动状态。使用 GameObject.activeInHierarchy
来读取 GameObject 是否实际处于场景中活动状态。需要使用 GameObject.activeInHierarchy
,因为 GameObject 是否实际处于活动状态由它自己的活动状态及其所有父类的活动状态决定。如果其任一父级未处于活动状态,那么它将不会处于活动状态,尽管它自己设置了活动状态。
Unity 的一些系统(例如 全局光照一群技术用于对直接和间接照明进行建模以实现真实的照明效果。
请参阅 术语表、遮挡、批处理、导航和 反射探头一种渲染组件,可以捕捉它周围环境的球形视图,就像一个照相机。捕获的图像随后以多维数据集的形式储存,可以被带有反射材料的物体使用。 更多信息
请参阅 术语表)依赖于一个 GameObject 的静态状态。您可以使用 GameObjectUtility.SetStaticEditorFlags
来控制哪些 Unity 系统将 GameObject 视为 静态的。有关更多信息,请参阅 静态 GameObject。
标签为在场景中标记和识别 GameObject 类型提供了一个方法,图层提供了一个类似但又不同的方法,将成组 GameObject 纳入或排除在某些内置操作中,例如 渲染 或 物理碰撞。
有关如何在编辑器中使用标签和图层的更多信息,请参阅 标签您可以将引用词分配给一个或多个 GameObject,以帮助您识别 GameObject 以便实现脚本目的。例如,您可以在游戏中定义一个“Edible”标签,用于玩家能吃的任何物品。 更多信息
请参阅 术语表 和 图层Unity 中的图层可用于有选择地将组 GameObject 纳入或排除在某些流程或计算中。这包括摄像机渲染、灯光、物理碰撞或您自己的代码中的自定义计算。 更多信息
请参阅 术语表 的主要用户手册页。
您可以使用“GameObject.tag
”和“GameObject.layer
”属性通过脚本修改标记和层值。您还可以通过使用“CompareTag
”方法来有效地检查游戏对象的标记,该方法包括对标记是否存在进行验证,并且不会导致任何内存分配。
您可以在运行时添加或删除组件,这对于通过程序创建游戏对象或修改游戏对象的行为很有用。请注意,您还可以通过脚本启用或禁用脚本组件和某些类型的内置组件,而不销毁它们。
在运行时添加组件的最佳方式是使用“AddComponent<Type>
”,按所示指定尖括号内的组件类型。若要删除组件,您必须对组件本身使用“Object.Destroy
”方法。
最简单的情况是游戏对象上的脚本需要访问附加到同一游戏对象的另一个组件(请记住,附加到游戏对象的其它脚本也是组件本身)。为此,第一步是获取您要使用的组件实例的引用。这是通过“GetComponent”方法完成的。通常,您需要将组件对象分配给变量,这是使用以下代码完成的。在此示例中,脚本正在获取同一游戏对象上“Rigidbody允许游戏对象受到模拟重力和其它力的影响的组件。 更多信息
请参见术语表”组件的引用
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”,只需使用脚本类名(或文件名)来指定您想要的组件类型即可。
如果您尝试检索尚未实际添加到 GameObject 中的组件类型,GetComponent 将返回 null。如果您尝试更改 null 对象上的任何值,您将在运行时收到一个 null 引用错误。
尽管它们有时独立运行,但脚本通常用于跟踪其他 GameObject,或者更常见的是,其他 GameObject 上的组件。例如,在烹饪游戏中,厨师可能需要知道炉灶的位置。Unity 提供了不同的方法来检索其他对象,每种方法都适用于特定情况。
找到相关 GameObject 的最直接方法是向脚本中添加一个公共 GameObject 变量
public class Chef : MonoBehaviour
{
public GameObject stove;
// Other variables and functions...
}
此变量将显示在检查器中,作为GameObject 字段。
您现在可以将场景或层次结构面板中的某个对象拖到此变量上以分配它。
GetComponent 函数和组件访问变量可用于此对象,就像用于任何其他对象一样,因此您可以使用如下代码
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;
}
}
此外,如果您在脚本中声明了一个组件类型的公共变量,则可以拖动已附加此组件的任何 GameObject。这直接访问组件而不是 GameObject 本身。
public Transform playerTransform;
当您处理具有永久连接的单个对象时,将对象用变量链接起来最有用。您可以使用数组变量链接多个相同类型的对象,但无论如何都必须在 Unity 编辑器中建立连接,而不是在运行时建立连接。在运行时定位对象通常很方便,Unity 提供了两种基本方法来执行此操作,如下所示。
有时,游戏场景会使用多种相同类型的 GameObject,例如收藏品、路点和障碍物。这些可能需要由一个特定的脚本来跟踪,该脚本负责监督或对其做出反应(例如,路径查找脚本可能需要所有路点)。使用变量链接这些 GameObject 是一种可能性,但如果每个新路点必须拖到脚本上的变量,则此方法会使设计过程变得乏味。同样,如果删除了一个路点,则必须删除对缺失 GameObject 的变量引用会很麻烦。在这种情况下,通常最好通过使它们全部成为一个父 GameObject 的子级来管理一组 GameObject。可以使用父项的Transform 组件Transform 组件确定场景中每个对象的位置、旋转和缩放。每个 GameObject 都具有 Transform。了解更多信息
请参阅 词汇表(因为所有 GameObject 隐式地都有 Transform)来检索子 GameObject。
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("煎锅");
当游戏对象具有可以在游戏过程中添加和移除的子游戏对象时,这很有用。例如可以拿起来或在游戏中放下的工具或炊具。
在编辑项目时,可以在检查器中设置游戏对象之间的引用。但是,有时无法提前设置它们(例如,在游戏中查找离角色最近的物品,或引用在场景加载后实例化的游戏对象)。在这些情况下,你可以在运行时查找引用并在游戏对象之间发送消息。
BroadcastMessage
允许你发送对具名方法的调用,而无需具体说明该方法应在哪实现。你可以使用它在特定游戏对象或其任何子对象的每个 MonoBehaviour 上调用具名方法。你还可以选择强制要求至少有一个接收者(或生成错误)。
SendMessage
具体一些,只向游戏对象本身(而不是其子对象)上的具名方法发送调用。
SendMessageUpwards
类似,但会向游戏对象及其所有父级上的具名方法发送调用。
只要你有一些信息来识别场景层次结构中的游戏对象,你就可以随时找到它们。可以使用 GameObject.Find 函数按名称检索单个对象
GameObject player;
void Start()
{
player = GameObject.Find("MainHeroCharacter");
}
还可以使用 GameObject.FindWithTag 和 GameObject.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
表示脚本,而非游戏对象。它实际上只会销毁调用它的脚本组件,并且使游戏对象保持原样,但会删除脚本组件。
游戏对象类提供基于脚本的替代方案,可替代 Unity 中的游戏对象菜单中可用的选项,允许你创建原语。
要创建 Unity 的内置原语实例,请使用 GameObject.CreatePrimitive,这会实例化指定类型的原语。可用的原语类型有球体、胶囊、圆柱体、立方体、平面和四边形类似于平面的原语对象,但其边缘只有 1 个单位长,它仅使用 4 个顶点,并且表面定向到局部坐标空间的 XY 平面中。 更多信息
请在词汇表中查看。