Unity3D中关于场景销毁时事件调用顺序的一点记录

先说一下我遇到的问题,我弄了一个对象池管理多个对象,对象池绑定在一个GameObject上,每个对象在OnBecameInvisible时会进行回收(即移出屏幕就回收),但是当场景切换或停止运行程序时场景中如果还有待回收的对象,就会报错,报错显示的信息为,我的对象池GameObject已经被销毁了云云,因为回收的对象我会把他们作为绑定了对象池的GameObject的子级来方便管理。

所以唯一的可能就是脚本方法调用顺序不可控,即不同GameObject的OnBecameInvisible在其它GameObject的OnDestroy之后调用。

在Unity3D中,我们知道GameObject的Update和LateUpdate两个函数的执行顺序是:每一帧中所有GameObject的Update方法都优先LateUpdate方法执行,即所有GameObject的Update方法都执行完毕才会执行LateUpdate方法。

那么我在使用下面3个方法时也认为其执行顺序也同Update和LateUpdate一致:

  • OnBecameInvisible:当GameObject存在renderer属性时,消失(不渲染)时会调用;
  • OnDisable:SetActivite(false)时调用;
  • OnDestroy:销毁时调用;

我认为在关闭程序或场景销毁时,其调用顺序是所有GameObject的OnBecameInvisible调用完毕后才开始调用OnDisable,最后再统一调用OnDestroy方法,即和Update与LateUpdate逻辑一致。

但是实际上并不是这样,对于每个GameObject来说,实际调用顺序是OnDisable->OnBecameInvisible->OnDestroy,但是在多个GameObject直接不能保证调用顺序,可能第一个GameObject的OnDestroy已经调用了,另一个的OnDisable才开始调用,大家可以用下面的脚本在场景中多放几个GameObject测试一下看看,注意要添加一个显示的东西,比如Cube,否则OnBecameInvisible不会调用到。

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class NewBehaviourScript : MonoBehaviour
 5 {
 6     public string name;
 7 
 8     void OnBecameInvisible()
 9     {
10         Debug.Log(name + " : OnBecameInvisible");
11     }
12 
13     void OnDisable()
14     {
15         Debug.Log(name + " : OnDisable");
16     }
17     
18     void OnDestroy()
19     {
20         Debug.Log(name + " : OnDestroy");
21     }
22 }

结果可以印证多个GameObject之间的方法调用顺序不能保证,所以我们开发程序在遇到场景销毁时管理一些对象时要注意。

我的解决方法:

实在想不出更好的办法了,要么让对象池GameObject在切换场景时不销毁,要么只有添加判断,如果对象池GameObject已经销毁了就不要进行对象回收。

大家可以参考一下国外的这个问题:

http://answers.unity3d.com/questions/505088/

原文地址:https://www.cnblogs.com/hammerc/p/4818403.html