zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    第二周
    第一周
    构建之法阅读笔记之三
    冲刺一(10)
    冲刺一(9)
    用户模板和用户场景
    冲刺一(8)
    第10周总结
    冲刺一(7)
    冲刺一(6)
  • 原文地址:https://www.cnblogs.com/hammerc/p/4818403.html
Copyright © 2011-2022 走看看