父物体禁用导致子物体组件未注册的Bug
问题描述
在业务中遇见了这样一个Bug,对象池创建小球,并且唤起小球的随机设置颜色功能。实际运行时,前两次或者第二次小球总是默认的颜色。
进一步细化Bug:
对象池没有命中的时候,小球的颜色总是随机的,比如:超出池中现有对象数量。但是只要没有超出对象池即对象池命中的时候,小球的颜色每次都没有变。
问题原因
通过打断点发现,在前两次创建小球的时候,拿不到小球的颜色组件,所以小球颜色没有更改。等拿到组件的时候,是小球的父物体被 SetActive 的时候。
简化原因: 小球本该在 Awake 的时候设置颜色,但是由于父物体被禁用,所以直到父物体启用,才会走小球的 Awake 周期,进而注册组件。
简化模型,做一个Demo
搭建了这样一个场景:
有一个 CubeSample(右),就待在右边。
有一个 CubeTest(左),挂了一个 CubeExpand.cs 脚本,并制作成了 Prefab,会在 Awake 的时候把自身 LocalScale 设置为 2,也就是放大 2 倍。
// CubeExpand.cs
using UnityEngine;
public class CubeExpand : MonoBehaviour
{
private void Awake()
{
transform.localScale = Vector3.one * 2;
SLog.DebugLog($"[CubeExpand] Awake frame:{Time.frameCount}");
}
}有一个空物体 ScriptObj,挂了一个 AwakeTest.cs,引用了 CubeTest Prefab 和 Root,用来在 Root 下实例化 CubeTest Prefab。 shouldActiveRoot 用来控制在 Awake 的时候是否要把 Root 启用。
// AwakeTest.cs
using UnityEngine;
public class AwakeTest : MonoBehaviour
{
public GameObject Root;
public GameObject CubeTestPrefab;
private GameObject cubeInstance;
public bool shouldActiveRoot = true;
private void Awake()
{
SLog.DebugLog($"[Test Awake] frame:{Time.frameCount}");
Root.SetActive(shouldActiveRoot);
cubeInstance = Instantiate(CubeTestPrefab, Root.transform);
}
void OnEnable()
{
SLog.DebugLog($"[Test OnEnable] frame:{Time.frameCount}");
}
private void Start()
{
SLog.DebugLog($"[Test Start] frame:{Time.frameCount}");
Root.SetActive(true);
}
}预期结果 与 Log Output:
shouldActiveRoot = true,AwakeTest 在 Awake 的时候,会显示出 Cube 并把自己放大两倍。
shouldActiveRoot = false,AwakeTest 在 Start 的时候,才会显示出 Cube 并把自己放大两倍。

结论
所以,在父物体被禁用的时候,子物体就算实例化了也不会走Awake,并且此时可以拿到子物体的引用(通过 Instantiate)。直到父物体启用的时候,此时子物体也同时被启用,走一遍子物体的生命周期。
相关链接
- https://docs.unity3d.com/cn/2022.3/Manual/ExecutionOrder.html
- https://docs.unity3d.com/6000.0/Documentation/Manual/execution-order.html
标题:父物体禁用导致子物体组件未注册的Bug
作者:LeonYew
日期:2025-10-16