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/

时间: 2024-12-22 01:08:22

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

AJAX 中Sys.WebForms.PageRequestManager的事件激发顺序

测试代码: [c-sharp] view plaincopy 测试代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="AjaxCtpWebDemo.Test" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona

AJAX 中Sys.WebForms.PageRequestManager的事件激发顺序 《转》

AJAX 中Sys.WebForms.PageRequestManager的事件激发顺序 测试代码: 测试代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="AjaxCtpWebDemo.Test" %> <!DOCTYPE html PUBLIC "-//W3C//DTD X

android中canvas的clipRect和concate调用顺序不同导致的图像效果不同。

这几天一直弄关于Canvas方法调用顺序不同导致效果不一样的測试. 至于原理,我的canvas和Matrix之间的关系能够看到原因.还是就是每一个人要多去尝试,才干真正理解透彻. 接下来我解说一下第一张图五个标签的意义: 第一顺序图片是正常全屏显示在800*1280的手机上的.没有任务效果.只是原图是720*1280,所以为了满足手机的屏幕大小,他进行了等倍数的放大. 第二顺序图效果是进行PolyToPoly之后的图片,没有进行区域剪切. 第三顺序图是先剪切显示区域,然后PolyToPoly以后

创建如Unity3D中Scene场景中的编辑轴

问题分析: 最近在搞软件底层开发,将一些工具或者底层脚本打成dll导入unity使用,有这样一需求,就是编辑功能,需要像Scene场景一样,实现那种编辑轴 实现方式: 创建Mesh,构建编辑轴,这个地方这么几步: 1.线(轴) 2.圆(旋转线) 3.正方形(轴面) 4.圆锥(轴方向) 具体步骤: 1.创建线Mesh: 代码: 1 /// <summary> 2 /// 创建线Mesh 3 /// </summary> 4 /// <param name="start

Unity3D中切换场景可能导致材质变暗的问题

Unity版本:5.1.1f1 做公司项目的时候,无意间发现了一个很奇葩的现象:场景A(纯UI,故没有光源)转场到场景B的时候,B中原有的光源似乎失效了,但在Hierarchy窗口中能够看到光源存在,调整光源的明度参数,效果也是有的,只是看起来仍然非常暗. 而直接加载B场景就没有任何问题. 上图说明问题.我制作了两个场景,A场景没有灯光,有一个跳转到B场景的按钮: B场景有光源,有一个跳转到A场景的按钮,还放了一个圆柱体用于表现材质问题: 这是直接加载B场景的效果: 这是从A场景跳转B场景的效果

Vue中在组件销毁时清除定时器(setInterval)

在mounted中创建并执行定时器,然后在beforeDestroy或者destroyed中清除定时器 <template> <div class="about"> </div> </template> <script> export default { name: "about", data() { return { //接收定时器 timer: "" }; }, mounted()

ajax中Sys.WebForms.PageRequestManager的事件激发顺序

测试代码: [c-sharp] view plaincopyprint? 测试代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="AjaxCtpWebDemo.Test" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans

Java中的try catch finaly先后调用顺序

自我总结,有什么不足或好的方案,希望大家给予纠正,感激不尽! 目的:try catch finaly的顺序执行,和大家复习一遍. 方法:debug来确认执行顺序.(需要引入junit包) 废话不多说,debug是检验代码执行顺序的唯一标准,哈哈... 测试一: 新建测试类:ExceptionTest package com.core.test007; import org.junit.Test; public class ExceptionTest { @Test public void mai

lua 中关于时间戳和可读时间格式的一点记录

lua 标准库中提供了关于时间的函数os.time()和os.date(),这两个函数使用起来还是有需要注意的地方的:这两个函数的结果都是加入了时区:比如我现在系统是GMT+8; os.time({year=1970, month=1, day=1, hour=0})计算出来的是-28800,也就是86060:计算的是当前table中给定的时间距离1970.1.1 08:00时间的秒数,所以就得到负数了: C标准库中,time()函数得到的时间戳其实也是加入了时区,也就是说不管你系统是那个时区,