How to Develop a Game
GameObject
PublishDate: 2025-05-28 | CreateDate: 2025-05-28 | LastModify: 2025-05-28 | Creator:ljf12825

GameObject继承自Object,是所有可以存在于场景中的物体的基类

可以理解为 Unity 世界中一切可见或不可见物体的“容器”,它本身没有实际行为或外观,而是通过添加各种组件(Component)来赋予其功能。

一、GameObject的核心概念

GameObjectinInspector

Active status

默认是激活状态,可以手动设置为非激活状态,在非激活状态下,GameObject会变得不可见,不会接收任何的回调或事件

可以通过GameObject.SetActive设置

Static status

Unity的某些系统(例如全局照明、遮挡、批处理、导航和反射探针)依赖于GameObject的静态状态,可以使用GameObjectUtility.SetStaticEditorFlags来控制Unity的哪些系统将GameObject视为静态的

Tag and Layer

Tag

Layer

二、GameObject的结构与组成

一个GameObject至少包含一个组件:Transform

1.必备组件:Transform

transform.position = new Vector3(0, 1, 0);
transform.Rotate(Vector3.up, 90);

2.常见组件

组件作用
MeshRenderer渲染模型表面
Collider物理碰撞检测
Rigidbody让 GameObject 参与物理计算
Animator控制动画状态机
AudioSource播放声音
Camera摄像头视角
Light光源
自定义脚本实现逻辑行为(继承自 MonoBehaviour

3.添加组件方式

gameObject.AddComponent<ComponentName>();

三、GameObject生命周期

生命周期由脚本组件(MonoBehaviour)控制

四、GameObject常用操作

1.创建与销毁

GameObject obj = new GameObject("MyObject"); // Create Empty Object
Destroy(obj);

2.获取组件

ComponentName varname = GetComponent<CompoenentName>();

3.控制启用状态

gameObject.SetActive(false);
someObj.SetActive(true);

4.层级控制

childObj.transform.parent = parentObj.transform; //设置父子关系

五、GameObject与Prefab的关系

Instantiate(prefabObject, position, rotation);

示例:创建一个带物理的球体对象

void CreateBall()
{
    GameObject ball = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    ball.transform.position = new Vector(0, 10, 0);
    ball.AddComponent<Rigidbody>();
}

API

Properties

属性类型描述
activeInHierarchybool (只读)当前对象是否在场景中激活(包括父对象也必须激活)
activeSelfbool (只读)当前对象自身的激活状态(不考虑父对象)
isStaticbool是否标记为静态对象,用于静态合批、光照贴图等优化
layerint当前对象所属的层(Layer),用于摄像机渲染、物理碰撞等
sceneScene当前 GameObject 所在的场景(Scene)
sceneCullingMaskulong (只读)对象的视锥剔除掩码,通常用于内部渲染优化
tagstring对象的标签(Tag),用于查找和分类管理
transformTransform (只读)GameObject 所关联的Transform 组件,用于位置、旋转、缩放控制

Constructors

构造器描述
GameObject()创建一个新的GameObject
GameObject(string name)具名
GameObject(string name, params Type[] components)组件列表
GameObject go = new GameObject("go", typeof(Rigidbody), typeof(BoxCollider));

Public Methods

方法名描述
AddComponent<T>()向当前 GameObject 添加指定类型的组件
GetComponent<T>()获取当前 GameObject 上的第一个指定类型组件
TryGetComponent<T>(out T component)安全尝试获取指定类型的组件(不抛出异常)
GetComponents<T>()获取当前 GameObject 上所有指定类型组件(数组)
GetComponentInChildren<T>()获取当前或子物体上的第一个指定类型组件
GetComponentsInChildren<T>()获取当前及所有子物体上的所有指定类型组件
GetComponentInParent<T>()获取当前或父物体上的第一个指定类型组件
GetComponentsInParent<T>()获取当前及所有父物体上的所有指定类型组件
GetComponentAtIndex(int index)获取组件数组中指定索引位置的组件
GetComponentCount()获取当前 GameObject 上组件的总数
GetComponentIndex(Component component)获取指定组件在组件数组中的索引
SendMessage(string methodName)调用当前 GameObject 上所有脚本中的指定方法
BroadcastMessage(string methodName)向当前 GameObject 及其所有子物体广播调用方法
SendMessageUpwards(string methodName)向当前 GameObject 及其所有父物体广播调用方法
SetActive(bool value)启用或禁用当前 GameObject(仅影响自身)
CompareTag(string tag)检查当前 GameObject 是否具有指定标签

Static Methods

方法名描述
CreatePrimitive(PrimitiveType type)创建一个具有网格渲染器和适当碰撞体的基础类型物体(如 Cube、Sphere 等)
Find(string name)根据名称查找并返回场景中第一个匹配的激活的 GameObject
FindGameObjectsWithTag(string tag)返回所有具有指定标签的激活 GameObject 数组;无匹配则返回空数组
FindWithTag(string tag)返回第一个具有指定标签的激活 GameObject;无匹配则返回 null
GetScene(int instanceID)获取包含指定实例 ID 的 GameObject 所在的场景
InstantiateGameObjects(GameObject prefab, int count, NativeArray<int> outIDs, NativeArray<Transform> outTransforms)批量实例化指定数量的 GameObject,并用 NativeArray 返回它们的 ID 和 Transform(通常用于 Job 系统)
SetGameObjectsActive(NativeArray<int> instanceIDs, bool active)批量设置多个通过实例 ID 标识的 GameObject 的激活状态

Unity官方文档(GameObject)

示例

添加和移除组件

可以在运行时添加和移除组件,这在动态创建GameObject或修改GameObject行为时非常有用,可以在脚本中使用enabledisable启用和禁用组件

添加组件最好的方式是使用AddComponent<Type>,如下所示。移除组件必须对组件本身使用Object.Destroy方法

获取组件

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

获取组件实例的引用后,可以设置值和调用方法

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

    rb.mass = 10f;
    rb.AddForce(Vector3.up * 10f);
}

一个GameObject可以挂载多个自定义脚本组件,它们之间可以通过GetComponent相互访问,如果GameObject上没有这个组件,返回null

获取其他GameObject上的组件

public class Chef : MonoBehaviour
{
    public GameObject stove;

    void Start()
    {
        transform.position = stove.transform.position + Vector3.forward * 2f;
    }
}

如果只需要使用组件功能,建议直接声明组件,减少调用链,面向组件编程(推荐)

查找子GameObject

如果一个场景中存在多个相同类型的对象与其手动一个个挂引用,不如通过父子结构统一管理,这是更灵活、自动化的方式

将同类对象放到一个父GameObject下,然后通过父物体的Transform来访问它们所有的子物体,从而动态获取并管理它们

比如有多个路径点:

Waypoints父物体
|—— Waypoint1
|—— Waypoint2
|—— Waypoint3

不需要在代码中这样声明

public GameObject waypoint1;
public GameObject waypoint2;
public GameObject waypoint3;

很不方便,可以这样做:

public class PathManager : MonoBehaviour
{
    public Transform waypointsParent; // 拖入Waypoints父物体

    private Transform[] waypoints;

    void Start()
    {
        // 获取所有子物体
        int count = waypointsParent.childCount;
        waypoints = new Transform[count];

        for (int i = 0; i < count; ++i)
            waypoints[i] = waypointsParent.GetChild(i);
    }

    void Update()
    {
        // 示例:绘制所有路点
        foreach (Transform wp in waypoints)
        {
            Debug.DrawLine(wp.position, wp.position + Vector3.up * 2, Color.green);
        }
    }
}

这样做的优点:

通过Tag或Name查找GameObject

GameObject player;

void Start() => player = GameObject.Find("MainHeroCharacter");
GameObject chef;
GameObject[] stoves;

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

创建和销毁对象

GameObject obj = new GameObject("MyNewObject"); // 具名,只有Transform组件
obj.AddComponent<Rigidbody>();
obj.AddComponent<BoxCollider>();

从预制体Prefab创建

public GameObject enemyPrefab; // 拖入预制体
void SpawnEnemy()
{
    GameObject enemy = Instantiate(enemyPrefab, new Vector3(0, 0, 0), Quaternion.identity);
}

将子物体挂在其他物体下

GameObject child = new GameObject("Child");
child.transform.parent = parentTransform;

child.transform.SetParent(parentTransform, worldPositionStays: false);