跳到主要内容

GameObject 基础

GameObject 是 Unity 中最核心的概念,场景中的所有对象都是 GameObject。本章将深入讲解 GameObject 的工作原理和使用方法。

什么是 GameObject

GameObject 是 Unity 场景中所有实体的基类。它可以代表角色、道具、特效、灯光、摄像机等任何存在于场景中的事物。

GameObject 的本质

一个 GameObject 本质上是一个容器,它本身没有任何功能,而是通过附加**组件(Component)**来实现各种功能:

GameObject (空容器)
└── Components (功能组件)
├── Transform (必需) - 定义位置、旋转、缩放
├── MeshRenderer - 渲染 3D 模型
├── Rigidbody - 物理模拟
└── 自定义脚本 - 游戏逻辑
核心原则

GameObject = 容器 + 组件集合

Unity 采用组件化架构(Component-Based Architecture),这种设计的优势在于:

  • 灵活性:自由组合不同功能
  • 复用性:组件可在不同对象间复用
  • 解耦:功能独立,便于维护

创建 GameObject

通过编辑器创建

Hierarchy 窗口右键菜单

右键点击 Hierarchy 窗口空白处
├── 3D Object # 3D 对象
│ ├── Cube # 立方体
│ ├── Sphere # 球体
│ ├── Capsule # 胶囊体
│ ├── Cylinder # 圆柱体
│ ├── Plane # 平面
│ └── Quad # 四边形
├── 2D Object # 2D 对象
│ ├── Sprite # 精灵
│ ├── Square # 正方形
│ ├── Circle # 圆形
│ └── Tilemap # 瓦片地图
├── Effects # 特效
│ ├── Particle System # 粒子系统
│ └── Trail # 轨迹
├── Light # 灯光
├── Audio # 音频
├── Video # 视频
├── UI # 用户界面
└── Create Empty # 创建空对象

通过代码创建

using UnityEngine;

public class CreateObjectExample : MonoBehaviour
{
void Start()
{
// 方法1:创建空 GameObject
GameObject emptyObject = new GameObject("MyEmptyObject");

// 方法2:创建基本 3D 对象
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = "MyCube";

// 方法3:实例化预制体(Prefab)
// GameObject instance = Instantiate(prefabReference);

// 设置父对象
cube.transform.SetParent(emptyObject.transform);
}
}

创建基本图元

Unity 提供了几种内置的基本几何体:

// 创建立方体
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

// 创建球体
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);

// 创建胶囊体
GameObject capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule);

// 创建圆柱体
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);

// 创建平面
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
关于 Quad 和 Plane
  • Quad:1x1 单位大小的单面四边形,适合 UI 和 2D 效果
  • Plane:10x10 单位大小的单面平面,适合作为地面

组件系统详解

Transform 组件

每个 GameObject 都必须有 Transform 组件,它是唯一不能移除的组件。

// 获取 Transform 组件
Transform trans = gameObject.transform;

// 常用属性
Vector3 position = trans.position; // 世界坐标位置
Vector3 localPosition = trans.localPosition; // 本地坐标位置
Quaternion rotation = trans.rotation; // 世界坐标旋转
Vector3 eulerAngles = trans.eulerAngles; // 欧拉角(度)
Vector3 localScale = trans.localScale; // 本地缩放

// 常用方法
trans.Translate(Vector3.forward); // 平移
trans.Rotate(Vector3.up, 90f); // 旋转
trans.LookAt(target); // 看向目标

添加和移除组件

通过编辑器

  1. 选中 GameObject
  2. Inspector 窗口点击 Add Component
  3. 搜索并选择需要的组件

通过代码

// 添加组件
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
BoxCollider collider = gameObject.AddComponent<BoxCollider>();

// 获取组件
Rigidbody existingRb = gameObject.GetComponent<Rigidbody>();

// 获取子对象中的组件
Rigidbody childRb = gameObject.GetComponentInChildren<Rigidbody>();

// 获取父对象中的组件
Rigidbody parentRb = gameObject.GetComponentInParent<Rigidbody>();

// 获取所有组件
Component[] allComponents = gameObject.GetComponents<Component>();

// 移除组件
Destroy(rb); // 销毁组件
Destroy(collider);

常用内置组件

组件类型用途典型场景
Transform位置、旋转、缩放所有对象
MeshRenderer渲染 3D 模型可见物体
SpriteRenderer渲染 2D 精灵2D 游戏
Rigidbody物理模拟需要物理效果的对象
Collider碰撞检测所有可碰撞对象
Camera渲染场景主摄像机
Light照明光源
AudioSource播放音频音效来源
Animator播放动画角色动画
ParticleSystem粒子特效特效对象

对象激活状态

GameObject 可以被激活或禁用,禁用的对象不会渲染、不执行脚本、不参与物理。

通过编辑器控制

Inspector 窗口顶部的复选框控制对象激活状态:

☑ MyGameObject    ← 勾选为激活,取消为禁用

通过代码控制

// 检查激活状态
bool isActive = gameObject.activeSelf; // 自身激活状态
bool isActiveInHierarchy = gameObject.activeInHierarchy; // 在层级中是否有效

// 设置激活状态
gameObject.SetActive(true); // 激活
gameObject.SetActive(false); // 禁用

// 激活子对象(不影响父对象)
transform.GetChild(0).gameObject.SetActive(true);
注意区别
  • activeSelf:对象自身的激活设置
  • activeInHierarchy:考虑父对象后的实际激活状态

如果父对象被禁用,子对象的 activeInHierarchy 会是 false,即使 activeSelf 是 true。

对象标签和层

标签(Tag)

标签用于标识和分类 GameObject,便于查找和区分。

Unity 内置标签

  • Untagged:默认无标签
  • Respawn:重生点
  • Finish:终点
  • EditorOnly:仅在编辑器中显示
  • MainCamera:主摄像机
  • Player:玩家
  • GameController:游戏控制器

自定义标签

  1. 选中对象,Inspector 中点击 Tag 下拉菜单
  2. 选择 Add Tag...
  3. 在 Tags & Layers 窗口添加新标签

代码中使用标签

// 设置标签
gameObject.tag = "Enemy";

// 比较标签(推荐方式)
if (gameObject.CompareTag("Player"))
{
// 这是玩家对象
}

// 不推荐:字符串比较
// if (gameObject.tag == "Player") { }

// 通过标签查找对象
GameObject player = GameObject.FindWithTag("Player");
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");

层(Layer)

层用于控制渲染、物理碰撞、射线检测等行为。

内置层

  • Default (0):默认层
  • TransparentFX (1):透明特效
  • Ignore Raycast (2):忽略射线检测
  • Water (4):水
  • UI (5):用户界面

常用自定义层

  • Player:玩家层
  • Enemy:敌人层
  • Ground:地面层
  • Obstacle:障碍物层
  • Item:物品层

代码中使用层

// 设置层(使用层索引)
gameObject.layer = 8; // 第8层

// 设置层(使用层名称)
gameObject.layer = LayerMask.NameToLayer("Enemy");

// 获取层名称
string layerName = LayerMask.LayerToName(gameObject.layer);

// 层遮罩(用于射线检测等)
LayerMask enemyMask = LayerMask.GetMask("Enemy");
LayerMask groundMask = LayerMask.GetMask("Ground", "Obstacle");

对象查找方法

查找单个对象

// 通过名称查找(全局搜索,效率低)
GameObject obj = GameObject.Find("Player");

// 通过标签查找(推荐)
GameObject player = GameObject.FindWithTag("Player");
GameObject player = GameObject.FindGameObjectWithTag("Player");

// 通过类型查找(查找带有特定组件的对象)
PlayerController pc = FindObjectOfType<PlayerController>();
Camera mainCam = FindObjectOfType<Camera>();

查找多个对象

// 查找所有带特定标签的对象
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");

// 查找所有带特定组件的对象
PlayerController[] players = FindObjectsOfType<PlayerController>();

// 现代推荐方式(避免 GC)
List<PlayerController> players = new List<PlayerController>();
FindObjectsOfType(players);

Transform 层级查找

// 获取父对象
Transform parent = transform.parent;

// 获取根对象
Transform root = transform.root;

// 获取子对象
Transform child = transform.GetChild(0); // 获取第1个子对象
int childCount = transform.childCount; // 子对象数量

// 通过名称查找子对象
Transform foundChild = transform.Find("ChildName");
Transform deepChild = transform.Find("Parent/Child/GrandChild"); // 支持路径

// 遍历所有子对象
foreach (Transform child in transform)
{
Debug.Log(child.name);
}
性能警告
  • GameObject.FindFindObjectOfType 开销较大,避免在 Update 中调用
  • 建议在 StartAwake 中缓存查找结果
  • 对于频繁访问的对象,使用 public 字段或 SerializeField 在 Inspector 中引用

对象销毁

// 销毁对象(延迟到本帧结束)
Destroy(gameObject);

// 延迟销毁(2秒后)
Destroy(gameObject, 2f);

// 立即销毁(谨慎使用,可能引发问题)
DestroyImmediate(gameObject);

// 销毁组件
Destroy(GetComponent<Rigidbody>());

// 销毁子对象
Destroy(transform.GetChild(0).gameObject);

父子关系管理

设置父对象

// 方法1:直接设置 parent(已过时,不推荐使用)
// transform.parent = parentTransform;

// 方法2:使用 SetParent(推荐)
transform.SetParent(parentTransform);

// 保持世界坐标不变
transform.SetParent(parentTransform, true);

// 保持本地坐标不变
transform.SetParent(parentTransform, false);

// 解除父子关系
transform.SetParent(null);

父子关系的作用

// 父对象移动,子对象跟随
parent.position = new Vector3(10, 0, 0);
// child.position 也会相应变化

// 子对象的 Transform 是相对于父对象的
child.localPosition = Vector3.zero; // 子对象位于父对象中心

// 应用场景:角色装备系统
// 武器作为手的子对象,跟随手部移动
weapon.transform.SetParent(handTransform);

实践示例

示例1:创建简单的敌人

using UnityEngine;

public class EnemySpawner : MonoBehaviour
{
public Material enemyMaterial;

void Start()
{
CreateEnemy("Enemy1", new Vector3(0, 1, 0), Color.red);
CreateEnemy("Enemy2", new Vector3(5, 1, 0), Color.blue);
CreateEnemy("Enemy3", new Vector3(-5, 1, 0), Color.green);
}

GameObject CreateEnemy(string name, Vector3 position, Color color)
{
// 创建立方体
GameObject enemy = GameObject.CreatePrimitive(PrimitiveType.Cube);
enemy.name = name;
enemy.tag = "Enemy";
enemy.layer = LayerMask.NameToLayer("Enemy");

// 设置位置
enemy.transform.position = position;

// 设置材质颜色
Renderer renderer = enemy.GetComponent<Renderer>();
renderer.material = new Material(enemyMaterial);
renderer.material.color = color;

// 添加刚体
Rigidbody rb = enemy.AddComponent<Rigidbody>();
rb.mass = 2f;

// 添加自定义脚本
enemy.AddComponent<EnemyController>();

return enemy;
}
}

示例2:对象池管理

using UnityEngine;
using System.Collections.Generic;

public class ObjectPool : MonoBehaviour
{
public GameObject prefab;
public int poolSize = 20;

private Queue<GameObject> pool = new Queue<GameObject>();

void Start()
{
// 预创建对象
for (int i = 0; i < poolSize; i++)
{
GameObject obj = Instantiate(prefab);
obj.SetActive(false);
pool.Enqueue(obj);
}
}

public GameObject GetFromPool()
{
if (pool.Count > 0)
{
GameObject obj = pool.Dequeue();
obj.SetActive(true);
return obj;
}

// 池耗尽时创建新对象
return Instantiate(prefab);
}

public void ReturnToPool(GameObject obj)
{
obj.SetActive(false);
pool.Enqueue(obj);
}
}

最佳实践

  1. 使用预制体(Prefab):对于重复使用的对象,创建预制体而非代码生成
  2. 缓存组件引用:在 AwakeStart 中缓存常用组件
  3. 避免频繁查找:不要在 Update 中使用 Find 方法
  4. 合理使用层级:通过父子关系组织场景,保持 Hierarchy 整洁
  5. 命名规范:使用有意义的名称,便于识别和管理

下一步

理解 GameObject 后,你可以:

  1. 深入学习 Transform 变换 控制对象位置和旋转
  2. 编写 C# 脚本 添加交互逻辑
  3. 了解 物理系统 实现碰撞和物理效果