(转)MOMO的Unity3D研究院之深入理解Unity脚本的执行顺序(六十二)

http://www.xuanyusong.com/archives/2378

Unity是不支持多线程的,也就是说我们必须要在主线程中操作它,可是Unity可以同时创建很多脚本,并且可以分别绑定在不同的游戏对象身上,他们各自都在执行自己的生命周期感觉像是多线程,并行执行脚本的,它是如何执行的呢?

我们做一个小小的实验来验证它。如下图所示,在Hierarchy视图中创建三个游戏对象,在Project视图中创建三条脚本,然后按照顺序将脚本绑定在对应的游戏对象身上。

屏幕快照 2013-06-20 上午11.41.00

三条脚本的代码完全一样,只是做了一点名称上的区分,代码写的比较丑我们只是作为测试!!

view source
01using UnityEngine;
02using System.Collections;
03 
04public class Script0 : MonoBehaviour
05{
06 
07    void Awake ()
08    {
09        Debug.Log("Script0 ========= Awake");
10    }
11 
12    bool isUpdate = false;
13    void Update ()
14    {
15        if(!isUpdate)
16        {
17            Debug.Log("Script0 ========= Update");
18            isUpdate = true;
19        }
20    }
21 
22    bool isLateUpdate = false;
23    void LateUpdate()
24    {
25        if(!isLateUpdate)
26        {
27            Debug.Log("Script0 ========= LateUpdate");
28            isLateUpdate = true;
29        }
30    }
31}

 播放游戏,看看他们的执行顺序。如下图所示,Awake、Update、LateUpdate、无论播放游戏多少次,他们执行的顺序是完全一样的。

69E7A099-2FDA-4E25-824E-7D10FA4FB6A1

 

 

接着我们在做一个测试,把Script0的Update方法注释掉!!

view source
01using UnityEngine;
02using System.Collections;
03 
04public class Script0 : MonoBehaviour
05{
06 
07    void Awake ()
08    {
09        Debug.Log("Script0 ========= Awake");
10    }
11 
12//  bool isUpdate = false;
13//  void Update ()
14//  {
15//      if(!isUpdate)
16//      {
17//          Debug.Log("Script0 ========= Update");
18//          isUpdate = true;
19//      }
20//  }
21 
22    bool isLateUpdate = false;
23    void LateUpdate()
24    {
25        if(!isLateUpdate)
26        {
27            Debug.Log("Script0 ========= LateUpdate");
28            isLateUpdate = true;
29        }
30    }
31}

 播放游戏,在看看它的结果。脚本的执行顺序和以前完全一样,Script0即使删除掉了Update方法,但是它也不会直接执行LateUpdate方法,而是等待Script1和Script2的Update方法都执行完毕以后,在去执行所有的LateUpdate方法。

 

7FD750FD-0567-4A97-820D-7576057E341C

 

通过这两个例子我们就可以清楚的断定Unity后台是如何执行脚本的了。每个脚本的Awake、Update、LateUpdate、FixedUpdate等等,方法在后台都有一个总汇。

后台的Awake()

{

       脚本0中的Awake();

       脚本1中的Awake();

       脚本2中的Awake();

}

       后台的方法 Awake、Update、LateUpdate、FixedUpdate等等都是按照顺序,等所有子脚本中的Awake执行完毕后在去执行 Start 、Update、LateUpdate等等。所以这里也就解释了Unity没有多线程的概念。

后台的Update()

{

       脚本0中的Update();

       脚本1中的Update();

       脚本2中的Update();

}

Unity还提供的一组协同任务的方法,其实它的原理和上面的完全一样,它们都是假的多线程。说了一圈我们又回到了Unity脚本的执行顺序上来?我们在看两条脚本!

在脚本2的Awake方法中创建一个立方体对象。

view source
01using UnityEngine;
02using System.Collections;
03 
04public class Script2 : MonoBehaviour
05{
06    void Awake ()
07    {
08        GameObject.CreatePrimitive(PrimitiveType.Cube);
09    }
10}

在脚本0的Awake方法中去获取这个立方体对象 

view source
01using UnityEngine;
02using System.Collections;
03 
04public class Script0 : MonoBehaviour
05{
06 
07    void Awake ()
08    {
09        GameObject go = GameObject.Find("Cube");
10        Debug.Log(go.name);
11    }
12 
13}

 

          如果脚本的执行顺序是 先执行Script2 然后在执行Script0那么Script0中的Awake就可以获取到该立方体对象,可是如果脚本的执行顺序是先Script0然后在Script2,那么Script0肯定会报空指针错误的。

          那么实际项目中的脚本会非常非常多,他们的先后顺序我们谁也不知道。所以我的建议一般在Awake方法中创建游戏对象或在Resources.Load(Prefab) 对象。在Start方法中去获取游戏对象,或者游戏组件,这样就可以确保万无一失了。

     如果说你非要控制脚本的执行先后顺序,也不是完全不行!Unity可以设置脚本执行的顺序。如下图所示,选择任意脚本在Inspector视图中点击Execution Order..按钮。

74591B1B-AF1B-4743-BE9B-E2710853CECB

如下图所示,点击右下角的“+”将弹出下拉窗口,包括游戏中的所有脚本。添加脚本完毕后,Default Time下方数值越小的排在越前面脚本将率先执行,如果没有设置的脚本将按默认的顺序执行。

屏幕快照 2013-06-20 下午12.16.00

 

按照我的这个设置,程序将先执行Script0然后Script1最后Script2,欢迎一起讨论!!哇咔咔。。

转载于:https://www.cnblogs.com/hisiqi/p/3204870.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378058.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL/MongoDB 连接并发测试

最近一直在搞mongodb 文件服务器大量文件并发上传测试,在官方文档发现mongo是线程安全的,支持单一连接下的并发操作。印象ADO.NET 似乎不支持单一连接并发。于是,测试一下来证实这个疑虑。(前两篇小记一直纠结mongodb吃内存导致并…

【C、C++基础】什么时候用 “.” 什么时候用“->”(3个实例搞懂)

从堆栈的角度来说: 从堆栈的角度来说: 对象放在堆上,就要用指针,也就是对象指针->函数; 放在栈上,就对象.函数 那么如何判断对象放在堆上还是栈上? 从我的另一篇笔记【C grammar】C简化内存模型可知&am…

java clone方法_Java Calendar clone()方法与示例

java clone方法日历类clone()方法 (Calendar Class clone() method) clone() method is available in java.util package. clone()方法在java.util包中可用。 clone() method is used to return the cloned object of this Calendar object. clone()方法用于返回此Calendar对象…

三、Numpy数组操作

一、对图片各个像素点的像素值进行操作 image.shape[0]:image图像的height image.shape[1]:image图像的width image.shape[2]:image图像的channels import cv2 import numpy as npdef access_pixels(image):print(image.shape)height imag…

picacg服务器维护,picacg的服务器地址是什么

弹性云服务器 ECS弹性云服务器(Elastic Cloud Server)是一种可随时自助获取、可弹性伸缩的云服务器,帮助用户打造可靠、安全、灵活、高效的应用环境,确保服务持久稳定运行,提升运维效率三年低至5折,多种配置可选了解详情用户数据注…

Redis-Sampler:深入了解你的Redis存储

redis-sampler 是Redis作者antirez 同学开发的一个ruby 小工具,用于对Redis存储概况进行抽样检测并给出分析结果。 项目地址:https://github.com/antirez/redis-sampler 使用方式: 下载源码,执行下面命令: ./redis-sam…

二叉树笔记(深度遍历与广度遍历+13道leetcode题目(深度3道、广度10道))

本文章为结合leetcode题目以及公众号“代码随想录”的文章所做的笔记! 感觉代码随想录的题目整理真的很好,比自己盲目刷题好很多。 目录1、二叉树小记1、满二叉树与完全二叉树2、二叉搜索树3、平衡二叉搜索树AVL4、二叉树存储方式5、二叉树遍历方式6、二…

ZZ的计算器

Problem Description ZZ自从上大学以来,脑容量就是以SB计算的,这个吃货竟然连算术运算也不会了,可是当今的计算机可是非常强大的,作为ACMer, 几个简单的算术又算得了什么呢?可是该怎么做呢?ZZ只…

kotlin 覆盖属性_Kotlin程序| 方法覆盖的示例

kotlin 覆盖属性方法重载 (Method Overriding) Method overriding allows derived class has the same function name and signature as the base class 方法重写允许派生类具有与基类相同的函数名称和签名 By method overriding we can provide different implementation into…

对视频中的特征颜色物体(青色水杯)进行跟踪

方法一:目标物体白色,其余黑色 import cv2 import numpy as npdef extrace_object():capture cv2.VideoCapture("G:/Juptyer_workspace/study/data/yy.mp4")while(True):ret,frame capture.read()if retFalse:breakhsv cv2.cvtColor(frame…

Android实现号码归属地查询

我们通过发送XML访问 WebService就可以实现号码的归属地查询,我们可以使用代理服务器提供的XML的格式进行设置,然后请求提交给服务器,服务器根据请求就会返回给一个XML,XML中就封装了我们想要获取的数据。 发送XML 1.通过URL封装路…

如何从 Datagrid 中获得单元格的内容与 使用值转换器进行绑定数据的转换IValueConverter...

一、如何从 Datagrid 中获得单元格的内容 DataGrid 属于一种 ItemsControl, 因此,它有 Items 属性并且用ItemContainer 封装它的 items. 但是,WPF中的DataGrid 不同于Windows Forms中的 DataGridView。 在DataGrid的Items集合中,DataGridRow…

【C++ grammar】常量、指针、Usage of using, typedef, and #define

目录1、常量 (Constant)2、指针(Pointer)3、Usage of using, typedef, and #define1、常量 (Constant) 常量是程序中一块数据,这个数据一旦声明后就不能被修改了。 如果这块数据有一个名字&am…

斯威夫特山地车_斯威夫特| 两个数字相加的程序

斯威夫特山地车In this program, we will have an idea - how two numbers can be added and displayed as the output on the screen? 在此程序中,我们将有一个想法- 如何将两个数字相加并显示为屏幕上的输出 ? Open XCode terminal and type the fol…

四、色彩空间

一、色彩空间 1、什么是色彩空间? 色彩空间是定义的颜色范围。 2、常见的色彩空间有哪些? ①RGB ②HSV 在OpenCV中,Hue的值为0~180,之所以不是360是因为,8位存不下,故进行归一化操作,使得H…

Oracle LOB 详解

一. 官方说明Oracle 11gR2 文档:LOB Storagehttp://download.oracle.com/docs/cd/E11882_01/appdev.112/e18294/adlob_tables.htm#ADLOB45267Oracle 10gR2 文档:LOBs in Tableshttp://download.oracle.com/docs/cd/B19306_01/appdev.102/b14249/adlob_t…

FIFA的完整形式是什么?

国际足联:国际足球联合会 (FIFA: Federation Internationale de Football Association) FIFA is an abbreviation of the "Federation Internationale de Football Association" in French. It is also known as the International Federation of Associa…

POJ 1654 Area

题意:从原点出发,沿着8个方向走,每次走1个点格或者根号2个点格的距离,最终回到原点,求围住的多边形面积。分析:直接记录所经过的点,然后计算多边形面积。注意,不用先保存所有的点&am…

【C++ grammar】重载、内联、变量作用域、带默认参数的函数

目录1、变量的作用域1. 变量的作用域分类2. Unary Scope Resolution (一元作用域解析运算符)2、重载函数3、带有默认参数值的函数4、重载函数 VS 带有默认参数值的函数5、内联函数(Inline Function)1. 普通函数的优缺点2. 使用内联函数3. 定义内联函数4.…

五、像素运算

一、相关概念 1、算术运算 Ⅰ加减乘除 Ⅱ调节亮度 Ⅲ调整对比度 2、逻辑运算 Ⅰ与或非 Ⅱ遮罩层控制 二、图像算术运算(加减乘除均值方差) 其中图像的加减乘除需要保证两张图像的大小相同 import cv2 import numpy as npdef add(src1,src2):dst cv2.add(src1,src2)cv2.im…