Unity3D熱更新之LuaFramework篇[03]--prefab載入和Button事件
在上一篇文章 Unity3D熱更新之LuaFramework篇[02]--用Lua建立自己的面板 中 ,我介紹了LuaFramework載入面板的方法,但這個方法並不適用於其它Prefab資源,在這套框架中非面板型資源的載入方法另有套路。
1、如何載入非面板預製體
1、建立一個預製體
開啟上次使用的工程,開啟Main場景,建立一個名為ImgOrc的Image,圖片就選例子用的獸人頭像。在Assets/LuaFramework/CustomPrj目錄下新建一個Prefabs目錄,然後拖動ImgOrc到該目錄下做成預製體,如圖1-1
圖1-1
2、將預製體打成AssetBundle包
開啟Assets/ LuaFramework/Editor/Packager.cs檔案(用VS或Mono Develop編輯器開啟),找到HandleExampleBundle方法,新增對ImgOrc預製體的打包程式碼,如圖1-2所示
圖1-2
1/// <summary> 2/// 處理框架例項包 3/// </summary> 4static void HandleExampleBundle() { 5string resPath = AppDataPath + "/" + AppConst.AssetDir + "/"; 6if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath); 7 8AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt"); 9AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message"); 10 11//打包我們新加的FirstPanel預製體 12AddBuildMap("first" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/FirstTest"); 13//打包我們新加的ImgOrc預製體 14AddBuildMap("prefabs" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/Prefabs"); 15 16AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt"); 17AddBuildMap("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared"); 18} 打包程式碼
這裡要對AddBuildMap方法的引數加以說明
- 第一個引數是包名,即打包後在StreamingAssets目錄中顯示的包的名稱,AppConst.ExtName是副檔名,框架預設為".unity3d",可以自行修改;
- 第三個引數是要打包的資源的目錄,暫且稱為源目錄;
- 第二個引數是打包模式,以字串形式過濾出要打包的檔名,比如這裡*.prefab就表示源目錄下的所有prefab檔案。
之所以將ImgOrc預製體打包的包名定義為prefabs而不是ImgOrc,是因為這個打包是針對整個目錄的而不是單個資源。為了說明這一情況,我會在CustomPrj/Prefabs目錄下再加一個預製體ButtonPrefab。見圖1-3
見圖1-3
這次不修改打包檔案。
找到 LuaFramework 選單,點選 Build Windows Resources 選單項,開始自動打包操作,中間無需干預。
打包結束,檢視StreamingAssets目錄,能看到與剛剛給定的包名相應的檔案:prefabs.unity3d,見圖1-4
圖1-4
圖中紅框標識的還有一個名為prefabs的檔案,這是沒有顯示字尾(其實有後綴,在unity中未顯示),這個是prefabs.unity3d包的清單檔案,在windows下開啟看以看到其全名為prefabs.unity.manifest。
用Notepad++開啟這個清單檔案,可以看到在37、38行列出一這個AB包包含的兩個資源:ButtonPrefab.prefab和ImgOrc.Prefab。見圖1-5:
圖1-5
此框架的資源打包方式就是這樣的,所有資源都需要在程式碼中新增相應包名、過濾模式、目錄。遊戲開發前期和資源變動較大時,會頻繁改動這個指令碼的內容,用起來並不是很方便。
3、在程式碼中載入預製體
資源包有了,現在需要在程式碼中載入這個包。
開啟FirstCtrl.lua檔案,在FirstCtrl.OnCreate方法中新增讀取資源包的方法,見程式碼:
--啟動事件-- function FirstCtrl.OnCreate(obj) gameObject = obj; message = gameObject:GetComponent('LuaBehaviour'); --載入prefabs.unity3d資源包 resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs) end); end
resMgr是框架封裝好的資源管理工具,LoadPrefab函式用來讀取資源包。第一個引數是包名,第二個引數是包裡的資源名(Prefab名稱),第三個引數是包讀取成功的回撥,引數prefabs為讀出來的資源。
..
繼續完成程式碼,進行例項操作等操作,程式碼如下:
1 --啟動事件-- 2 function FirstCtrl.OnCreate(obj) 3gameObject = obj; 4transform = obj.transform; 5 6message = gameObject:GetComponent('LuaBehaviour'); 7 8--載入prefabs.unity3d資源包 9resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs) 10log(prefabs.Length); --輸出 1 11log(prefabs[0].name) --輸出 ImgOrc 12 13--載入獸人頭像到FirstPanel下 14local go = newObject(prefabs[0]); --例項化 15go.transform:SetParent(transform); --設定FirstPanel為父物件 16go.transform.localPosition = Vector3.zero; --設定初始位置 17go.transform.localScale = Vector3.one; --設定縮放 18 19end); 20 end
說明點:
- 回撥函式的引數prefabs是一個userdata型別的資料(userdata一般是C#中的部分引用型別在Lua中的表示),這裡猜測是一個數組,因為通過.Length可以取到長度,能過[0]能取到第一個元素。
- newObject是框架封裝好的例項化函式,猜測本質就是c#中的GameObject.Instantiate方法。
- 設定父物件、位置、縮放這幾步操作和c#中的操作差不多。因為本身呼叫的就是c#中的方法,即transform的方法。
- FirstCtrl.lua檔案中的gameObject,transform代表的就是FirstPanel面板及面板上transform元件,是在面板建立時(OnCreate方法前兩行)注入進來的。
程式碼完成後,執行Unity,能看到ImgOrc已經載入到了FirstPanel物件下,見圖1-6
圖1-6
非Panel的預製體載入流程就是這樣,載入方法是參照例子的PromptCtrl.lua寫的。
resMgr中還有放多其它載入資源的方法,留待以後再探究。
2、怎麼給按鈕新增監聽
在用c#寫程式碼的時候,給Button新增監聽有兩種方法,一是將指令碼綁在Button元件上,通過面板選擇指令碼中的方法來新增做;二是在程式碼中通過Button.onClick.AddListener方法新增。
那麼在Lua應該怎麼做呢?
還是以FirstPanel為例,給FirstPanel右上角新增一個關閉按鈕,應用預製體然後重新打包,
然後:
1、在FirstPanel.lua檔案中引用按鈕
開啟FirstPanel.lua檔案,在InitPanel函式中新增查詢按鈕的程式碼:
--初始化面板-- function FirstPanel.InitPanel() --查詢關閉按鈕 this.btnClose = transform:FindChild("CloseButton").gameObject; end
2、在FirstCtrl.lua檔案中新增監聽
開啟FirstCtrl.lua檔案,找到OnCreate方法,然後通過FirstPanel所掛的LuaBehaviour指令碼來新增監聽事件,見圖2-1
圖2-1
AddClick方法有兩個引數,第一個是按鈕本身(上一步才引用過的),第二個是點選後的回撥函式。
AddClick的具體實現可以可以在LuaBehaviour.cs中找到。
執行Unity,點選關閉按鈕,能看到列印了期望中的日誌,見圖2-2
圖2-2
給按鈕新增監聽就是這麼簡單,不過裡邊還藏著一些坑,以後的文章再細講。
總結一點,用Lua做邏輯的話,所有UI元素的使用都需要先在相應的XxxPanel中引用 ,然後到XxxCtrl中新增事件,對於結構複雜的UI,做起來非常耗時間。
文中多次操作了FirstCtrl.lua和FirstPanel.lua檔案,為了方便參閱,現將兩個指令碼完整的貼出來:
1 local transform; 2 local gameObject; 3 4 FirstPanel = {}; 5 local this = FirstPanel; 6 7 --啟動事件-- 8 function FirstPanel.Awake(obj) 9gameObject = obj; 10transform = obj.transform; 11 12this.InitPanel(); 13logWarn("Awake lua--->>"..gameObject.name); 14 end 15 16 --初始化面板-- 17 function FirstPanel.InitPanel() 18--查詢關閉按鈕 19this.btnClose = transform:FindChild("CloseButton").gameObject; 20 end 21 22 --單擊事件-- 23 function FirstPanel.OnDestroy() 24logWarn("OnDestroy---->>>"); 25 end FirstPanel
1 FirstCtrl = {}; 2 local this = FirstCtrl; 3 4 local behaviour; 5 local transform; 6 local gameObject; 7 8 --構建函式-- 9 function FirstCtrl.New() 10logWarn("FirstCtrl.New--->>"); 11return this; 12 end 13 14 function FirstCtrl.Awake() 15logWarn("FirstCtrl.Awake--->>"); 16panelMgr:CreatePanel('First', this.OnCreate); 17 end 18 19 --啟動事件-- 20 function FirstCtrl.OnCreate(obj) 21gameObject = obj; 22transform = obj.transform; 23 24behaviour = gameObject:GetComponent('LuaBehaviour'); 25behaviour:AddClick(FirstPanel.btnClose, function () 26log("你點選了關閉"); 27end); 28 29--載入prefabs.unity3d資源包 30resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs) 31log(prefabs.Length); --輸出 1 32log(prefabs[0].name) --輸出 ImgOrc 33 34--載入獸人頭像到FirstPanel下 35local go = newObject(prefabs[0]); --例項化 36go.transform:SetParent(transform); --設定FirstPanel為父物件 37go.transform.localPosition = Vector3.zero; --設定初始位置 38go.transform.localScale = Vector3.one; --設定縮放 39 40end); 41 end 42 43 --單擊事件-- 44 function FirstCtrl.OnClick(go) 45destroy(gameObject); 46 end 47 48 --關閉事件-- 49 function FirstCtrl.Close() 50panelMgr:ClosePanel(CtrlNames.Message); 51 end FirstCtrl
本次的介紹就到這裡。