刚写 Unity 时,我把初始化全塞进 Start。对象默认启用时,这通常能跑通。后来做对象池,预制体反复开关,问题就来了:有的字段只初始化一次,有的却要每次亮起来都重绑。
我现在的分工
Awake:拿自己身上的组件,做一次即可的缓存。不依赖别的脚本已经 Start。OnEnable:订阅事件、重置“这次出场”需要的状态。对象池每次取出都会走这里。Start:依赖场景里其他对象已经 Awake 完的初始化。只跑一次。
void Awake()
{
_rigidbody = GetComponent<Rigidbody>();
}
void OnEnable()
{
_health = _maxHealth;
GameEvents.OnPlayerHit += HandleHit;
}
void OnDisable()
{
GameEvents.OnPlayerHit -= HandleHit;
}
订阅一定要在 OnDisable 里退订。对象被关掉后如果事件还指着它,下次再启用,或者场景卸载时,很容易出现空引用。
执行顺序
两个脚本都挂在同一个物体上时,Awake 的先后并不保证按你在 Inspector 里看到的顺序。需要严格先后时,我会用 Script Execution Order,或者让一方在 Start 再去问另一方。
备忘:OnDisable 不等于销毁。池子里休眠的对象不会走 OnDestroy,所以清理工作不能只写在 Destroy 里。