Unity3D中腳本的執(zhí)行順序和編譯順序

在Unity中可以同時(shí)創(chuàng)建很多腳本,并且可以分別綁定到不同的游戲?qū)ο笊献殚希鼈兏髯远荚谧约旱纳芷谥羞\(yùn)行。與腳本有關(guān)的也就是編譯和執(zhí)行啦,本文就來研究一下Unity中腳本的編譯和執(zhí)行順序的問題瓢省。

事件函數(shù)的執(zhí)行順序

先說一下執(zhí)行順序吧。

官方給出的腳本中事件函數(shù)的執(zhí)行順序如下圖:

我們可以做一個(gè)小實(shí)驗(yàn)來測試一下:

在Hierarchy視圖中創(chuàng)建三個(gè)游戲?qū)ο笕啵赑roject視圖中創(chuàng)建三條腳本勤婚,如下圖所示,然后按照順序?qū)⒛_本綁定到對應(yīng)的游戲?qū)ο笊希?/p>

三條腳本的代碼完全一樣涤伐,只是做了一點(diǎn)名稱上的區(qū)分:

using UnityEngine;

using System.Collections;

public class Scring0 : MonoBehaviour

{

void Awake()

{

Debug.Log("Script0 ======= Awake");

}

bool isUpdate = false;

void Update()

{

if(!isUpdate)

{

Debug.Log("Script0 ======= Update");

isUpdate = true;

}

}

bool isLateUpdate = false;

void LateUpdate()

{

if(!isLateUpdate)

{

Debug.Log("Script0 ======= LateUpdate");

isLateUpdate = true;

}

}

}

播放游戲馒胆,看看它們的執(zhí)行順序缨称。如下圖所示,Awake祝迂、Update睦尽、LateUpdate,無論運(yùn)行游戲多少次型雳,它們的執(zhí)行順序是完全一樣的当凡。

接著我們再做一個(gè)測試,把Script0的Update方法注釋掉>兰蟆沿量!

using UnityEngine;

using System.Collections;

public class Script0 : MonoBehaviour

{

void Awake ()

{

Debug.Log("Script0 ========= Awake");

}

//? bool isUpdate = false;

//? void Update ()

//? {

//????? if(!isUpdate)

//????? {

//????????? Debug.Log("Script0 ========= Update");

//????????? isUpdate = true;

//????? }

//? }

bool isLateUpdate = false;

void LateUpdate()

{

if(!isLateUpdate)

{

Debug.Log("Script0 ========= LateUpdate");

isLateUpdate = true;

}

}

}

再次運(yùn)行游戲,看看它的結(jié)果柑晒。腳本的執(zhí)行順序和以前完全一樣欧瘪,Script0即便刪除掉了Update方法,但是它也不會(huì)直接執(zhí)行LateUpdate方法匙赞,而是等待Script1和Script2中的Update方法都執(zhí)行完畢以后佛掖,再去執(zhí)行所有的LateUpdate方法。

通過這兩個(gè)例子涌庭,我們就可以很清楚地?cái)喽ń姹唬琔nity后臺(tái)是如何執(zhí)行腳本的了。每個(gè)腳本的Awake坐榆、Start拴魄、Update、LateUpdate席镀、FixedUpdate等等匹中,所有的方法在后臺(tái)都會(huì)被匯總到一起:

后臺(tái)的Awake()

{

// 這里暫時(shí)按照上圖中的腳本執(zhí)行順序,后面會(huì)談到其實(shí)可以自定義該順序的

腳本2中的Awake();

腳本1中的Awake();

腳本0中的Awake();

}

后臺(tái)的方法Awake豪诲、Update顶捷、LateUpdate等等,都是按照順序屎篱,等所有游戲?qū)ο笊夏_本中的Awake執(zhí)行完畢之后服赎,再去執(zhí)行Start、Update交播、LateUpdate等方法的重虑。

后臺(tái)的Update()

{

// 這里暫時(shí)按照上圖中的腳本執(zhí)行順序,后面會(huì)談到其實(shí)可以自定義該順序的

腳本2中的Update();

腳本1中的Update();

腳本0中的Update();

}

腳本的執(zhí)行順序然后我們來看看這樣一種情況:在腳本0的Awake方法中創(chuàng)建一個(gè)立方體對象秦士,然后在腳本2的Awake方法中去獲取這個(gè)立方體對象缺厉。代碼如下:

// Script0.cs

using UnityEngine;

using System.Collections;

public class Script0 : MonoBehaviour

{

void Awake ()

{

GameObject.CreatePrimitive(PrimitiveType.Cube);

}

}

// Script2.cs

using UnityEngine;

using System.Collections;

public class Script2 : MonoBehaviour

{

void Awake ()

{

GameObject go = GameObject.Find("Cube");

Debug.Log(go.name);

}

}

如果腳本的執(zhí)行順序是先執(zhí)行Script0,然后再執(zhí)行Script2,那么Script2中的Awake就可以正確地獲取到該立方體對象芽死;可是如果腳本的執(zhí)行順序是先執(zhí)行Script2乏梁,然后是Script0,那么Script2肯定會(huì)報(bào)空指針錯(cuò)誤的关贵。

那么實(shí)際項(xiàng)目中的腳本會(huì)非常多遇骑,它們的先后執(zhí)行順序我們誰也不知道(有人說是按照棧結(jié)構(gòu)來執(zhí)行的,即后綁定到游戲?qū)ο笊系哪_本先執(zhí)行揖曾。這一點(diǎn)可以從上面的例子中得到落萎,但官方并沒有這么說,還得進(jìn)一步深入研究)炭剪。但一般的练链,建議在Awake方法中創(chuàng)建游戲?qū)ο蠡騌esources.Load(Prefab)對象,然后在Start方法中去獲取游戲?qū)ο蠡蛘呓M件奴拦,因?yàn)槭录瘮?shù)的執(zhí)行順序是固定的媒鼓,這樣就可以確保萬無一失了。

另外错妖,Unity也提供了一個(gè)方法來設(shè)置腳本的執(zhí)行順序绿鸣,在Edit -> Project Settings -> Script Execution Order菜單項(xiàng)中,可以在Inspector面板中看到如下圖所示:

點(diǎn)擊右下角的"+"將彈出下拉窗口暂氯,包括游戲中的所有腳本潮模。腳本添加完畢后,可以用鼠標(biāo)拖動(dòng)腳本來為腳本排序痴施,腳本名后面的數(shù)字也越小擎厢,腳本越靠上,也就越先執(zhí)行辣吃。其中的Default Time表示沒有設(shè)置腳本的執(zhí)行順序的那些腳本的執(zhí)行順序动遭。

按照上面這張圖的設(shè)置,我們再來看一下控制臺(tái)的輸出結(jié)果神得,來確認(rèn)一下我們的設(shè)置是否起作用(注意:把Script0腳本中的Update方法取消注釋):

腳本的編譯順序

關(guān)于腳本的編譯順序很是頭疼沽损,官方的說法有點(diǎn)模糊,請看官方的解釋:

由于腳本的編譯順序會(huì)涉及到特殊文件夾循头,比如上面提到的Plugins、Editor還有Standard Assets等標(biāo)準(zhǔn)的資源文件夾炎疆,所以腳本的放置位置就非常重要了卡骂。下面用一個(gè)例子來說明不同文件夾中的腳本的編譯順序:

實(shí)際上,如果你細(xì)心的話會(huì)發(fā)現(xiàn)形入,如果在你的項(xiàng)目中建立如上圖所示的文件夾層次結(jié)構(gòu)時(shí)全跨,編譯項(xiàng)目之后會(huì)在項(xiàng)目文件夾中生成一些文件名中包含Editor、firstpass這些字樣的項(xiàng)目文件亿遂。比如按照上圖的文件夾結(jié)構(gòu)浓若,我們打開項(xiàng)目文件夾來看一下產(chǎn)生的項(xiàng)目文件是什么樣的渺杉?

下面就來詳細(xì)探討一下這些個(gè)字樣是什么意思?它們與腳本的編譯順序有著怎樣的聯(lián)系挪钓?

1是越、首先從腳本語言類型來看,Unity3d支持3種腳本語言碌上,都會(huì)被編譯成CLI的DLL

如果項(xiàng)目中包含有C#腳本倚评,那么Unity3d會(huì)產(chǎn)生以Assembly-CSharp為前綴的工程,名字中包含”vs”的是產(chǎn)生給Vistual Studio使用的馏予,不包含”vs”的是產(chǎn)生給MonoDevelop使用的天梧。

項(xiàng)目中的腳本語言 工程前綴 工程后綴 C# Assembly-CSharp csproj UnityScript Assembly-UnityScript unityproj Boo Assembly-Boo booproj

如果項(xiàng)目中這三種腳本都存在,那么Unity將會(huì)生成3種前綴類型的工程霞丧。

2呢岗、對于每一種腳本語言,根據(jù)腳本放置的位置(其實(shí)也部分根據(jù)腳本的作用蛹尝,比如編輯器擴(kuò)展腳本后豫,就必須放在Editor文件夾下),Unity會(huì)生成4中后綴的工程箩言。其中的firstpass表示先編譯硬贯,Editor表示放在Editor文件夾下的腳本。

在上面的示例中陨收,我們得到了兩套項(xiàng)目工程文件:分別被Virtual Studio和MonoDevelop使用(后綴包不包含vs)饭豹,為簡單起見,我們只分析vs項(xiàng)目务漩。得到的文件列表如下:

Assembly-CSharp-filepass-vs.csproj

Assembly-CSharp-Editor-filepass-vs.csproj

Assembly-CSharp-vs.csproj

Assembly-CSharp-Editor-vs.csproj

根據(jù)官方的解釋拄衰,它們的編譯順序如下:

(1)所有在Standard Assets、Pro Standard Assets或者Plugins文件夾中的腳本會(huì)產(chǎn)生一個(gè)Assembly-CSharp-filepass-vs.csproj文件饵骨,并且先編譯翘悉;

(2)所有在Standard Assets/Editor、Pro Standard Assets/Editor或者Plugins/Editor文件夾中的腳本產(chǎn)生Assembly-CSharp-Editor-filepass-vs.csproj工程文件居触,接著編譯妖混;

(3)所有在Assets/Editor外面的,并且不在(1),(2)中的腳本文件(一般這些腳本就是我們自己寫的非編輯器擴(kuò)展腳本)會(huì)產(chǎn)生Assembly-CSharp-vs.csproj工程文件轮洋,被編譯制市;

(4)所有在Assets/Editor中的腳本產(chǎn)生一個(gè)Assembly-CSharp-Editor-vs.csproj工程文件,被編譯弊予。

之所以按照這樣建立工程并按此順序編譯祥楣,也是因?yàn)镈LL間存在的依賴關(guān)系所決定的。

好了,到此為止误褪,我們可以很容易地判斷出上面舉的實(shí)例中责鳍,腳本的編譯順序(實(shí)際上,我已經(jīng)把順序?qū)懺诹四_本的文件名中了)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兽间,一起剝皮案震驚了整個(gè)濱河市历葛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌渡八,老刑警劉巖啃洋,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異屎鳍,居然都是意外死亡宏娄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門逮壁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孵坚,“玉大人,你說我怎么就攤上這事窥淆÷舫瑁” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵忧饭,是天一觀的道長扛伍。 經(jīng)常有香客問我,道長词裤,這世上最難降的妖魔是什么刺洒? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮吼砂,結(jié)果婚禮上逆航,老公的妹妹穿的比我還像新娘。我一直安慰自己渔肩,他們只是感情好因俐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著周偎,像睡著了一般抹剩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蓉坎,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天吧兔,我揣著相機(jī)與錄音,去河邊找鬼袍嬉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伺通。 我是一名探鬼主播箍土,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼罐监!你這毒婦竟也來了吴藻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤弓柱,失蹤者是張志新(化名)和其女友劉穎沟堡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矢空,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡航罗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屁药。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粥血。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酿箭,靈堂內(nèi)的尸體忽然破棺而出复亏,到底是詐尸還是另有隱情,我是刑警寧澤缭嫡,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布缔御,位于F島的核電站,受9級特大地震影響妇蛀,放射性物質(zhì)發(fā)生泄漏耕突。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一讥耗、第九天 我趴在偏房一處隱蔽的房頂上張望有勾。 院中可真熱鬧,春花似錦古程、人聲如沸蔼卡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雇逞。三九已至,卻和暖如春茁裙,著一層夾襖步出監(jiān)牢的瞬間塘砸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工晤锥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掉蔬,地道東北人廊宪。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像女轿,于是被迫代替她去往敵國和親箭启。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容