原文?http://www.kidsang.com/archives/741
? ? ?在制作UI界面的時候,我們需要獲取界面上的UI控件,以實現(xiàn)對UI界面的控制。比如,獲取文本框控件來輸入文字,或者獲取按鈕控件注冊事件回調(diào)。對于Unity3D來說,我們有兩種方式把某個控件關(guān)聯(lián)到某變量上。
靜態(tài)關(guān)聯(lián):在類中暴露public變量給編輯器,然后在編輯器中通過拖拽控件的方法把變量和控件關(guān)聯(lián)上。
動態(tài)關(guān)聯(lián):從UI界面的根節(jié)點(diǎn)開始向下遍歷,一直找到自己想要的控件。
如果可能的話,當(dāng)然最好是使用靜態(tài)關(guān)聯(lián)。這種方法不需要在游戲運(yùn)行時查找控件,效率高于動態(tài)關(guān)聯(lián),因此能提高界面的加載速度。然而這種方式的痛苦之處在于,我們需要手動為每個界面編寫對應(yīng)的類文件,暴露變量,并手動在編輯器中拖拽控件賦予變量??紤]到每個游戲都會有巨量的界面,能否使用自動的方式生成對應(yīng)的UI類文件,并自動關(guān)聯(lián)變量呢?這樣將會給界面開發(fā)提供巨大的便利,省去很多繁瑣的事。
第一步,根據(jù)Prefab生成UI類
這一步非常簡單,我們可以通過寫一個Editor腳本來完成這個工作:
實例化Prefab到場景
便利實例化后的GameObject,把所有含有UI控件的GameObject找出來,將他們的名字記錄下來
根據(jù)第2步記錄的信息生成UI類cs文件,保存。
把Prefab的InstanceID,和第2步中記錄的信息,以文本的形式保存為一個臨時文件。
為什么會有第4步的操作呢?這是為了給后續(xù)的操作用的。
第二步,關(guān)聯(lián)UI類中的變量和Prefab中的控件
這一步需要一些技巧。因為UI的類文件是我們剛剛生成的,尚未編譯,因此我們無法立刻通過GameObject.AddComponent()的方式將其添加到Prefab上。我曾經(jīng)嘗試過C#的反射機(jī)制立刻編譯新生成的UI類文件,并動態(tài)獲取類型,強(qiáng)行調(diào)用GameObject.AddComponent()將其加到Prefab上。然而,這種方式編譯出來的類信息處于另外一個Assembly 中(而不是Assembly-CSharp.dll),在編輯器中Prefab會顯示缺失類文件引用(script file missing)。顯然,我們需要讓Unity編輯器來編譯我們生成的文件,并等待它編譯完成后再執(zhí)行后續(xù)操作。
幸好,Unity編輯器提供了對應(yīng)的接口。首先,我們可以通過調(diào)用AssetDatabase.ImportAsset()或AssetDatabase.Refresh()觸發(fā)編輯器編譯代碼。然后,我們可以在Editor腳本中通過[UnityEditor.Callbacks.DidReloadScripts]屬性監(jiān)聽編譯完成事件。
由于Unity編輯器編譯完成后,會重載所有的DLL,所有內(nèi)存中的變量都會被清除。因此,我們只能文件的方式傳遞信息。在第一步的第4小步中,我們已經(jīng)把必要的信息保存成臨時文件,我們只需要讀取這個文件就能拿回我們想要的信息。
綜上所述,步驟如下:
監(jiān)聽[UnityEditor.Callbacks.DidReloadScripts]事件,等待編譯完成。
讀取臨時文件,獲取Prefab的名稱和InstanceID。
使用InstanceID獲取我們的Prefab。 GameObject uiGameObject =?EditorUtility.InstanceIDToObject(instanceID) as GameObject;
獲取我們游戲的Assembly ,并從中獲取剛編譯好的類。 Type myUIClass = typeof(AClassInMyGame).Assembly.GetType(“MyUIClass”);
使用GameObject.AddComponent()將UI類添加到Prefab上。 MyUIClass myUI = uiGameObject.AddComponent(myUIClass);
讀取臨時文件,獲取導(dǎo)出的控件信息和名稱,使用FieldInfo.SetValue()將控件賦予UI類中的變量。?MyUIClass.GetField(‘SomeVariable’).SetValue(myUI, uiControl)
保存Prefab,所有的控件和變量已成功關(guān)聯(lián)。