(轉)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.pswp.cn/news/378058.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378058.shtml
英文地址,請注明出處:http://en.pswp.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…