在上一篇文章 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> 4 static void HandleExampleBundle() { 5 string resPath = AppDataPath + "/" + AppConst.AssetDir + "/"; 6 if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath); 7 8 AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt"); 9 AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message"); 10 11 //打包我們新加的FirstPanel預制體 12 AddBuildMap("first" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/FirstTest"); 13 //打包我們新加的ImgOrc預制體 14 AddBuildMap("prefabs" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/Prefabs"); 15 16 AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt"); 17 AddBuildMap("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);
endresMgr是框架封裝好的資源管理工具,LoadPrefab函數用來讀取資源包。第一個參數是包名,第二個參數是包里的資源名(Prefab名稱),第三個參數是包讀取成功的回調,參數prefabs為讀出來的資源。
..
繼續完成代碼,進行實例操作等操作,代碼如下:
1 --啟動事件-- 2 function FirstCtrl.OnCreate(obj) 3 gameObject = obj; 4 transform = obj.transform; 5 6 message = gameObject:GetComponent('LuaBehaviour'); 7 8 --加載prefabs.unity3d資源包 9 resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs) 10 log(prefabs.Length); --輸出 1 11 log(prefabs[0].name) --輸出 ImgOrc 12 13 --加載獸人頭像到FirstPanel下 14 local go = newObject(prefabs[0]); --實例化 15 go.transform:SetParent(transform); --設置FirstPanel為父對象 16 go.transform.localPosition = Vector3.zero; --設置初始位置 17 go.transform.localScale = Vector3.one; --設置縮放 18 19 end); 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文件,為了方便參閱,現將兩個腳本完整的貼出來:
FirstPanel1 local transform; 2 local gameObject; 3 4 FirstPanel = {}; 5 local this = FirstPanel; 6 7 --啟動事件-- 8 function FirstPanel.Awake(obj) 9 gameObject = obj; 10 transform = obj.transform; 11 12 this.InitPanel(); 13 logWarn("Awake lua--->>"..gameObject.name); 14 end 15 16 --初始化面板-- 17 function FirstPanel.InitPanel() 18 --查找關閉按鈕 19 this.btnClose = transform:FindChild("CloseButton").gameObject; 20 end 21 22 --單擊事件-- 23 function FirstPanel.OnDestroy() 24 logWarn("OnDestroy---->>>"); 25 end
FirstCtrl1 FirstCtrl = {}; 2 local this = FirstCtrl; 3 4 local behaviour; 5 local transform; 6 local gameObject; 7 8 --構建函數-- 9 function FirstCtrl.New() 10 logWarn("FirstCtrl.New--->>"); 11 return this; 12 end 13 14 function FirstCtrl.Awake() 15 logWarn("FirstCtrl.Awake--->>"); 16 panelMgr:CreatePanel('First', this.OnCreate); 17 end 18 19 --啟動事件-- 20 function FirstCtrl.OnCreate(obj) 21 gameObject = obj; 22 transform = obj.transform; 23 24 behaviour = gameObject:GetComponent('LuaBehaviour'); 25 behaviour:AddClick(FirstPanel.btnClose, function () 26 log("你點擊了關閉"); 27 end); 28 29 --加載prefabs.unity3d資源包 30 resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs) 31 log(prefabs.Length); --輸出 1 32 log(prefabs[0].name) --輸出 ImgOrc 33 34 --加載獸人頭像到FirstPanel下 35 local go = newObject(prefabs[0]); --實例化 36 go.transform:SetParent(transform); --設置FirstPanel為父對象 37 go.transform.localPosition = Vector3.zero; --設置初始位置 38 go.transform.localScale = Vector3.one; --設置縮放 39 40 end); 41 end 42 43 --單擊事件-- 44 function FirstCtrl.OnClick(go) 45 destroy(gameObject); 46 end 47 48 --關閉事件-- 49 function FirstCtrl.Close() 50 panelMgr:ClosePanel(CtrlNames.Message); 51 end
本次的介紹就到這里。