跳到主要内容

GameObject

基础创建与销毁


https://docs.unity.cn/cn/current/ScriptReference/GameObject.html

https://docs.unity3d.com/6000.3/Documentation/ScriptReference/GameObject.html

1. 创建 GameObject

csharp

// 1.1 创建空物体
GameObject obj = new GameObject("MyObject");

// 1.2 使用预制体创建(实例化)
public GameObject prefab;
GameObject instance = Instantiate(prefab);

// 1.3 带位置和旋转的创建
GameObject instance = Instantiate(prefab, position, rotation);

// 1.4 创建带组件的物体
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

// 1.5 克隆现有物体
GameObject clone = Instantiate(originalObject);

2. 销毁 GameObject

csharp

// 2.1 立即销毁
Destroy(gameObject);

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

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

// 2.4 销毁所有特定标签的物体
GameObject[] objects = GameObject.FindGameObjectsWithTag("Enemy");
foreach (GameObject obj in objects)
{
Destroy(obj);
}

二、查找与访问

1. 查找单个 GameObject

csharp

// 1.1 通过名称查找
GameObject player = GameObject.Find("Player");

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

// 1.3 通过类型查找(第一个)
Camera mainCamera = GameObject.FindObjectOfType<Camera>();

// 1.4 查找所有指定类型的物体
Camera[] allCameras = GameObject.FindObjectsOfType<Camera>();

2. 层级关系查找

csharp

// 2.1 查找子物体(按名称)
Transform child = transform.Find("ChildName");
GameObject childObj = transform.Find("ChildName").gameObject;

// 2.2 查找所有子物体
foreach (Transform child in transform)
{
Debug.Log(child.name);
}

// 2.3 递归查找子物体
Transform FindDeepChild(Transform parent, string childName)
{
foreach (Transform child in parent)
{
if (child.name == childName)
return child;
Transform result = FindDeepChild(child, childName);
if (result != null)
return result;
}
return null;
}

三、组件管理

1. 获取组件

csharp

// 1.1 获取组件(如果存在)
Rigidbody rb = GetComponent<Rigidbody>();

// 1.2 强制获取组件(不存在则添加)
Rigidbody rb = GetComponent<Rigidbody>();
if (rb == null)
rb = gameObject.AddComponent<Rigidbody>();

// 1.3 扩展方法:安全获取
public static T GetOrAddComponent<T>(this GameObject obj) where T : Component
{
T component = obj.GetComponent<T>();
if (component == null)
component = obj.AddComponent<T>();
return component;
}
// 使用:gameObject.GetOrAddComponent<Rigidbody>();

// 1.4 获取子物体组件
MeshRenderer childRenderer = GetComponentInChildren<MeshRenderer>();

// 1.5 获取父物体组件
Rigidbody parentRb = GetComponentInParent<Rigidbody>();

2. 添加/移除组件

csharp

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

// 2.2 移除组件
Destroy(GetComponent<Rigidbody>());

// 2.3 禁用组件(而不是移除)
GetComponent<Renderer>().enabled = false;
GetComponent<Collider>().enabled = false;

3. 检查组件

csharp

// 3.1 检查是否存在组件
bool hasRigidbody = TryGetComponent<Rigidbody>(out Rigidbody rb);

// 3.2 检查多个组件
bool hasRenderer = GetComponent<Renderer>() != null;
bool hasCollider = GetComponent<Collider>() != null;

四、激活与状态管理

1. 激活状态

csharp

// 1.1 激活/禁用物体
gameObject.SetActive(true); // 激活
gameObject.SetActive(false); // 禁用(不会执行Update)

// 1.2 检查激活状态
bool isActive = gameObject.activeSelf;
bool isActiveInHierarchy = gameObject.activeInHierarchy;

// 1.3 激活层级中的父物体
transform.parent.gameObject.SetActive(true);

2. 标签管理

csharp

// 2.1 设置标签
gameObject.tag = "Player";

// 2.2 检查标签
if (gameObject.CompareTag("Player"))
{
// 玩家逻辑
}

// 2.3 安全比较标签(避免空引用)
bool isPlayer = gameObject.CompareTag("Player");

3. 层管理

csharp

// 3.1 设置层
gameObject.layer = LayerMask.NameToLayer("Player");

// 3.2 检查层
if (gameObject.layer == LayerMask.NameToLayer("Enemy"))
{
// 敌人逻辑
}

// 3.3 批量设置子物体层
void SetLayerRecursively(GameObject obj, int layer)
{
obj.layer = layer;
foreach (Transform child in obj.transform)
{
SetLayerRecursively(child.gameObject, layer);
}
}

五、父子关系与变换

1. 父子关系操作

csharp

// 1.1 设置父物体
transform.SetParent(parentTransform);

// 1.2 保持世界坐标
transform.SetParent(parentTransform, false);

// 1.3 保持局部坐标
transform.SetParent(parentTransform, true);

// 1.4 移除父物体
transform.SetParent(null);

// 1.5 获取父物体
GameObject parent = transform.parent?.gameObject;

2. 位置、旋转、缩放

csharp

// 2.1 位置操作
transform.position = new Vector3(0, 0, 0);
transform.localPosition = Vector3.zero;

// 2.2 移动物体
transform.Translate(Vector3.forward * Time.deltaTime);
transform.position += Vector3.up * 2f;

// 2.3 旋转操作
transform.rotation = Quaternion.identity;
transform.Rotate(Vector3.up, 90f);
transform.RotateAround(target.position, Vector3.up, 45f);

// 2.4 缩放操作
transform.localScale = new Vector3(2, 2, 2);

六、广播与消息系统

1. 发送消息

csharp

// 1.1 发送消息给自身
SendMessage("TakeDamage", 10f);

// 1.2 发送消息给子物体
BroadcastMessage("OnPlayerDeath");

// 1.3 发送消息给父物体
SendMessageUpwards("ChildTriggered", this);

// 1.4 使用现代方式(推荐)
GetComponent<IDamageable>()?.TakeDamage(10f);

2. 接收消息

csharp

void TakeDamage(float damage)
{
health -= damage;
}

void OnPlayerDeath()
{
// 处理玩家死亡
}

七、实用工具方法

1. 距离计算

csharp

// 1.1 计算距离
float distance = Vector3.Distance(transform.position, target.position);

// 1.2 检查距离范围
bool isInRange = Vector3.Distance(transform.position, player.position) < 10f;

// 1.3 方向向量
Vector3 direction = (target.position - transform.position).normalized;

2. 射线检测

csharp

// 2.1 从物体发射射线
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, 10f))
{
GameObject hitObject = hit.collider.gameObject;
}

// 2.2 球形检测
Collider[] colliders = Physics.OverlapSphere(transform.position, 5f);
foreach (Collider col in colliders)
{
if (col.CompareTag("Enemy"))
{
// 处理敌人
}
}

八、协程与延时操作

1. 延时操作

csharp

// 1.1 延时激活/销毁
StartCoroutine(DelayedAction());

IEnumerator DelayedAction()
{
yield return new WaitForSeconds(2f);
gameObject.SetActive(false);
}

// 1.2 延时实例化
IEnumerator SpawnEnemies()
{
while (true)
{
Instantiate(enemyPrefab, spawnPoint.position, Quaternion.identity);
yield return new WaitForSeconds(3f);
}
}

九、事件与回调

1. 碰撞检测

csharp

void OnCollisionEnter(Collision collision)
{
GameObject other = collision.gameObject;
Debug.Log($"与 {other.name} 发生碰撞");
}

void OnTriggerEnter(Collider other)
{
GameObject triggerObject = other.gameObject;
Debug.Log($"进入触发器:{triggerObject.name}");
}

2. 鼠标事件

csharp

void OnMouseDown()
{
Debug.Log("点击了物体:" + gameObject.name);
}

void OnMouseOver()
{
// 鼠标悬停
}

十、性能优化方法

1. 缓存组件

csharp

private Rigidbody rb;
private Renderer renderer;

void Awake()
{
// 在Awake中缓存常用组件
rb = GetComponent<Rigidbody>();
renderer = GetComponent<Renderer>();
}

void Update()
{
// 直接使用缓存的组件
rb.AddForce(Vector3.up);
}

2. 对象池

csharp

public class ObjectPool : MonoBehaviour
{
public GameObject prefab;
public int poolSize = 10;
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 GetObject()
{
if (pool.Count > 0)
{
GameObject obj = pool.Dequeue();
obj.SetActive(true);
return obj;
}
return Instantiate(prefab);
}

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

十一、实用扩展方法

csharp

public static class GameObjectExtensions
{
// 1. 安全获取或添加组件
public static T GetOrAddComponent<T>(this GameObject obj) where T : Component
{
T component = obj.GetComponent<T>();
if (component == null)
component = obj.AddComponent<T>();
return component;
}

// 2. 设置层级(包括子物体)
public static void SetLayerRecursively(this GameObject obj, int layer)
{
obj.layer = layer;
foreach (Transform child in obj.transform)
{
child.gameObject.SetLayerRecursively(layer);
}
}

// 3. 查找子物体(递归)
public static GameObject FindChildRecursively(this GameObject parent, string childName)
{
foreach (Transform child in parent.transform)
{
if (child.name == childName)
return child.gameObject;

GameObject result = child.gameObject.FindChildRecursively(childName);
if (result != null)
return result;
}
return null;
}

// 4. 销毁所有子物体
public static void DestroyAllChildren(this GameObject parent)
{
foreach (Transform child in parent.transform)
{
GameObject.Destroy(child.gameObject);
}
}

// 5. 检查是否在视线内
public static bool IsInView(this GameObject obj, Camera camera)
{
Vector3 viewportPoint = camera.WorldToViewportPoint(obj.transform.position);
return viewportPoint.z > 0 &&
viewportPoint.x > 0 && viewportPoint.x < 1 &&
viewportPoint.y > 0 && viewportPoint.y < 1;
}
}

十二、常见使用模式

1. 单例模式

csharp

public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }

void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}

2. 对象查找优化

csharp

// 避免在 Update 中频繁使用 GameObject.Find
public class Player : MonoBehaviour
{
private static Player instance;
public static Player Instance => instance;

void Awake()
{
instance = this;
}

// 其他地方可以通过 Player.Instance 访问
}

3. 组件依赖检查

csharp

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Collider))]
public class Movement : MonoBehaviour
{
private Rigidbody rb;

void Awake()
{
rb = GetComponent<Rigidbody>();
// Unity 会自动添加缺失的组件
}
}