赞
踩
生命周期是Unity开发过程中的核心思想,是技术进阶过程中必须深入了解的重点,了解对象生命周期前,要先理解类、对象与引用是怎么回事。
类 : 是定义在代码文件中,保存在硬盘上 ,是对象的蓝本,它描述了对象在内存中大概是什么样子的
对象:我们都知道.net将值类型存储在栈中,引用类型存储在堆中,这样做的原因是栈中的数据是轻量级的,而堆中的数据是重量级,目的是在应用程序在操作它们的时候比较方便存取,从而提高程序的运行速度。创建一个对象实例,用new+类名+(),就创建了一个对象实例,创建的这个对象实例是引用类型,被存储在托管堆中,以后就不用管它了,new关键字返回一个对象实例存在的地址,这个存储地址(引用)变量,被放在栈中,实际上应用程序在运行时都是操作的这个引用。
引用:上面说了,就是指 堆数据在堆中的地址,存储在栈上。
创建一个对象实例需要三步:
1.计算新的对象实例要用多少地址
2.如果堆中的地址够用,就将调用构造函数创建这个对象将把它放在内存指针指向的位置
3.返回对象的引用,并将指针指向下一个对象应该存放的地址。
接下来到了垃圾回收了! 如果在计算新对象所用空间时发现空闲内在已经不够用了,那么.net就会调用垃圾收集程序做一次垃圾收集。CLR逐个排查不可达的对象,对么在托管堆中这个排查会浪费大量的时间,为了优化这个排查过程,将堆上的每一个对象对归属为某一个代中。CLR将内存中的对象分为0~2代(.net2.0中)。其中
当内存中没有位置了,垃圾收集器就开始依次调查和收集0代对象中是否有不可达对象,如果是不可达的,就将它清除,如果是可达的对象就将它标记为1代;直到可以有足够的位置存放新对象,这时不一定所有的0代对象对被清除了,那么它们被标记为1代;(1代是否被标记为2代?)如果被0代对象全部排查过了了,还不够分配给新对象 ,那么就开始排查1代对象,没有被回收的1代对象被标记为2代。如果排查过1代对象仍然不够,就开始排查第2代,就是这样2代对象存在的时间很长。
1.静态构造函数:当程序集被加载的时候就被调用了,如果你的unity处于编辑状态时,此时你保存一个脚本(从而迫使重新编译),静态构造函数会立即被调用,因为unity加载了DLL。并且它将不会再次运行,永远只会执行一次,unity运行时,是不会再次执行了!在一个已部署的游戏上,这个构造器将会在unity加载过程的早期被调用!
2.非静态构造器:Unity将会在一个貌似随机的时间调用一个对象的默认构造器。当你编辑一个游戏时,在你保存一个脚本(从而迫使重新编译)后,这构造器将会被立马调用!程序运行时被随机调用多次,程序结束时也被调用了(自己测试发现),所以不要使用构造器去初始化字段的值,unity的Awake就是专门为这个目的设计的。
3**.Awake**: 只会被调用一次,在Start方法之前被调用! 主要用于字段值的初始化工作,禁用脚本,创建游戏对象,或者 Resources.Load(Prefab) 对象
4.Start:只执行一次,在Awake方法执行结束后执行,但在Update方法执行前执行, 主要用于程序UI的初始化操作,比如获取游戏对象或者组件
5.Update:每一帧执行的,监听用户输入,播放动画,当机器忙或者性能差的时候,他会停止执行,会产生停顿的感觉,例如一个人本来在1米的位置,突然到了5米的位置上,产生了跳帧,而下面的FixedUpdate方法则相反!会一米一米的去执行!(自己调试发现,Update是先于OnGUI执行的,且执行一次Update之后,会执行两次OnGUI)
6.FixedUpdate:不管当前机器忙不忙,都会保证每一帧执行一次!避免跳帧!固定更新。固定更新常用于移动模型等操作。
7.LateUpdate:先执行Update,然后才去执行lateUpdate(Update方法执行完,必定接着执行LateUpdate,而Update和FixedUpdate方法的执行顺序不确定,而且有时候FIxedUpdate执行了多帧,而Update却只执行了一帧,这就是因为跳帧的缘故造成的(取决于你的机器性能)!),如果现在有100个脚本,分别有100个 Update()函数,其中只有一个LateUpdate,那么在同一帧中,等待100个Update()执行完后,才执行这一个LateUpdate()。
8.OnGUI:在这里面进行GUI的绘制,且GUI是每帧擦除重绘的!仅仅只是绘制!没有生命周期的概念!所有关于绘制GUI的代码,都要直接或者间接地写到OnGUI方法中!
9.OnDestroy:当前脚本销毁时调用
10.OnEnable:脚本可用时被调用、如果脚本是不可用的,将不会被调用!
11.OnDisable:如果脚本被设置为不可用将会被执行,程序结束时也会执行一次!
父级操作子级
1.如果在父级的Awake方法里面设置子级的脚本不可用
那么仅仅只会执行子级里面的Awake方法,当子级被激活后(enabled=true),会先执行OnEnable,然后执行Start方法,Update等帧序列方法都会开始执行
2.如果在父级的Start方法里面设置子级的脚本不可用
那么会执行子集里面的Awake,OnEnable和OnDisable方法,当子级被激活后(enabled=true),会先执行OnEnable,然后执行Start方法,Update等帧序列方法也都会开始执行
子级操作父级
1.如果在子级的Awake方法里面设置父级的脚本不可用
那么会执行父级里面的Awake,OnEnable和OnDisable方法,当父级被激活后(enabled=true),会先执行OnEnable,然后执行Start方法,Update等帧序列方法都会开始执行
2.如果在子级的Start方法里面设置父级的脚本不可用
那么会执行父集里面的Awake,OnEnable,Start和OnDisable方法,当父级被激活后(enabled=true),会先执行OnEnable,Update等帧序列方法也都会开始执行
如果被激活的脚本之前没有调用Start方法,那么当此脚本被激活后,会调用一次Start方法!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。