Unity3D熱更新之LuaFramework篇[02]--用Lua建立本身的面板 Unity3D熱更新之LuaFramework篇[01]--從零開始 最好用的lua編輯器--------emmyl

在上篇文章 Unity3D熱更新之LuaFramework篇[01]--從零開始 中,咱們瞭解了怎麼得到一個可用的LuaFramework框架。html

本篇將我會先介紹一下如何配置Lua開發環境,而後分析在此框架中加載面板的流程,以及如何建立本身的面板。git

一、配置Lua開發環境

有一點要說明的是,使用此種方式(ToLua+LuaFramework)作熱更新,則意味着你的大部分邏輯都須要改用Lua語言來編寫。github

所以,開發前得先得配置好Lua開發環境。畢竟,工欲善其事,必先利其器。windows

環境配置大概分如下三個步驟:框架

1.安裝IntelliJ IDEA Community Edition 2018.2.4 x64

官網地址 http://www.jetbrains.com/idea/download/#section=windows編輯器

直接下載便可,下載 Community 版本,也就是社區版,免費的ide

2.下載Lua For Windows

https://github.com/rjpcomputing/luaforwindows/releases函數

下載最新的就行,而後安裝。post

3.安裝emmylua插件

安裝插件有2種方法,能夠直接搜插件庫安裝,或者下載好插件後本地加載。學習

 

以上安裝步驟均來自:三頁菌 的文章 最好用的lua編輯器--------emmylua使用匯總

其文章極其詳細的介紹瞭如何搭建並配置一個好用的Lua開發環境,請自行參考。

 

二、Lua中是怎麼加載一個面板的

在上一篇文章最後,咱們運行框架,最終顯示了一個Lua腳本動態建立的面板,即PromptPanel,如圖2-1所示。

圖2-1

翻看框架的目錄結構,會在Assets/LuaFrame/Examples/Builds/Prompt目錄找到兩個預製體,PromptPanel和PromptItem,也就是這個面板的主體和獸人頭像,如圖2-2所示。

圖2-2

用上一節中安裝的IntelliJ IDEA打開工程目錄,在Controller目錄和View目錄會找到與PromptPanel密切相關的兩個文件PromptCtrl.lua、PromptPanel.lua,如圖2-3所示

圖2-3

由目錄名稱可知,此框架採用了一種MVC結構,用以對代碼功能作區分。XxxPanel負責頁面顯示邏輯,XxxCtrl負責事件處理,示例沒有給出明顯的Model層,讀者能夠根據自身項目酌情添加。

繼續查看框架代碼,會在Logic/Game.lua中找到遊戲的入口:Game.OnInitOK函數,見圖2-4。

圖2-4

 在這個函數中,有3個重要邏輯:

一、初始化View

二、初始化Ctrl

三、啓動Ctrl

 一、初始化View

初始化View就是調用InitViewPanels這個函數,InitViewPanels函數用於加載View目錄下定義的XxxPanel,在Game.lua的17行中能夠看到定義。

function Game.InitViewPanels()
   for i = 1, #PanelNames do
      require ("View/"..tostring(PanelNames[i]))
   end
end

PanelName則是在LuaFramwwork/Lua/Common/define.lua的第7行中定義的,對應面板的名稱。

PanelNames = {
    "PromptPanel",    
    "MessagePanel",
}

 

二、初始化Ctrl

初始化Ctrl是指CtrlManager.Init();這句,能夠在LuaFramwwork/Lua/Logic/CtrlManager.lua第9行中看到相關定義。這個函數中經過調用New函數建立了Ctrl的實例。

function CtrlManager.Init()
    logWarn("CtrlManager.Init----->>>");
    ctrlList[CtrlNames.Prompt] = PromptCtrl.New();
    ctrlList[CtrlNames.Message] = MessageCtrl.New();
    return this;
end

 

 三、啓動Ctrl

啓動就是根據CtrlNames找到對應的Ctrl的實例,而後調用其Awake方法,見代碼:

    local ctrl = CtrlManager.GetCtrl(CtrlNames.Prompt);
    if ctrl ~= nil and AppConst.ExampleMode == 1 then
        ctrl:Awake();
    end

 

以上都是推測,

爲了驗證猜想的對不對,我把CtrlManager.GetCtrl(CtrlNames.Prompt)這一句改成CtrlManager.GetCtrl(CtrlNames.Message),若是此次加載出來的是MessagePanel,則說明上述過程推斷正確。

....

改完後運行,發現加載的仍是PromptPanel,難道確實是找錯地方了?

別急,這裏還涉及另外一個概念。

 在熱更框架中,程序運行的並非咱們在LuaFramework/lua目錄下編寫的代碼,而是在Assets/StreamingAssets目錄下的打包後的代碼,見圖2-5。

圖2-5 

那麼有什麼辦法讓咱們剛剛改的代碼生效呢?

思路有兩個:

  1. 將們的寫的代碼打包到StreamAssets中;
  2. 讓程序直接運行打包前的代碼;

思路1的操做方法是:執行LuaFramework菜單下的Build XXX Resources菜單(見圖2-6),由於我如今的程序是運行在Windows平臺,因此選擇Build Windows Resource

 

圖2-6

點擊菜單,等待從新打包完成。打包結束後,能看到整個StreamingAssets目錄中的內容都更新了,在裏邊能夠找到message和prompt相關的資源,見圖2-7。

圖2-7

從新運行後,獲得了想的結果,程序直接加載了MessagePanel面板,見圖2-8。

圖2-8

 

由此印證咱們對整個面板流程的加載的推測分析

 

關於思路2讓程序直接運行打包前的代碼,只須要關閉Lua的AssetBundle模式就行了。

找到LuaFramework/Scripts/ConstDefine/AppConst.cs文件,將LuaBundleMode = true;改成

LuaBundleMode = false;便可,見圖2-8,圖中是改過以後的。

圖2-8

 LuaBundleMode 改成false以後,Lua代碼修改後就無需從新Build xxx Resources就能直接看到效果。

儘管思路1和思路2是二選一便可的,但爲方便後邊的示例,這裏要統一修改成false。

 

三、如何建立本身的面板

在上一步的分析中,咱們得知建立一個面板須要先初始化View,再實例化Ctrl,而後調用Ctrl的Awake。這些都是代碼層面的,前提還有一個,咱們須要一個XxxPanel預製體。

總結一下,若是要建立一個咱們本身的面板,則須要以下步驟:

一、建立一個XxxPanel預製體

二、建立對應的XxxView

三、建立對應的XxxCtrl

四、添加CtrlNames及PanelNames

五、加載XxxCtrl

 

下面我將以FirstPanel爲例進行演示。

一、建立FirstPanel預製體。

在Hierarchy面板中建立一個FirstPanel,並在LuaFramework目錄下新建CustomPrj/FirstTest目錄,將FirstPanel拖到此作成預製體,見圖3-1。

圖3-1

而後刪掉Hierarchy面板中的FirstPanel,由於後面咱們會動態加載它。

二、建立FirstView.lua腳本。

在Lua/View目錄下建立一個FirstView的lua腳本,腳本結構參照MessageView編寫,以下:

local transform;
local gameObject;

FirstPanel = {};
local this = FirstPanel;

--啓動事件--
function FirstPanel.Awake(obj)
    gameObject = obj;
    transform = obj.transform;

    this.InitPanel();
    logWarn("Awake lua--->>"..gameObject.name);
end

--初始化面板--
function FirstPanel.InitPanel()
    --這句要註釋掉,由於咱們的FirstPanel中沒有按鈕
    --this.btnClose = transform:FindChild("Button").gameObject;
end

--單擊事件--
function FirstPanel.OnDestroy()
    logWarn("OnDestroy---->>>");
end
View Code

 

注:lua腳本的建立方法是在IDEA中,選中目錄,右鍵->New->Lua File。

三、建立FirstCtrl.lua腳本。

在Lua/Controller目錄下建立一個FirsCtrl的lua腳本,腳本結構參照MessagCtrl編寫,以下:

 1 FirstCtrl = {};
 2 local this = FirstCtrl;
 3 
 4 local message;
 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 
23     message = gameObject:GetComponent('LuaBehaviour');
24 
25     --這句要註釋掉,由於咱們的FirstPanel中沒有按鈕
26     --message:AddClick(MessagePanel.btnClose, this.OnClick);
27 
28     logWarn("Start lua--->>"..gameObject.name);
29 end
30 
31 --單擊事件--
32 function FirstCtrl.OnClick(go)
33     destroy(gameObject);
34 end
35 
36 --關閉事件--
37 function FirstCtrl.Close()
38     panelMgr:ClosePanel(CtrlNames.Message);
39 end
View Code

 

四、添加CtrlNames及PanelNames

在Lua/Common找到define.lua,在CtrlNames中添加 First = "FirstCtrl",在PanelNames中添加"FirstPanel",以下:

CtrlNames = {
    Prompt = "PromptCtrl",
    Message = "MessageCtrl",
    First = "FirstCtrl"
}

PanelNames = {
    "PromptPanel",    
    "MessagePanel",
    "FirstPanel"
}

 

五、加載FirstCtrl

在Lua/Logic/Game.lua文件的Game.OnInitOK函數中,將CtrlManager.GetCtrl()的參數修改成咱們剛剛添加的CtrlNames.First,以下所示:

    CtrlManager.Init();
    local ctrl = CtrlManager.GetCtrl(CtrlNames.First);
    if ctrl ~= nil and AppConst.ExampleMode == 1 then
        ctrl:Awake();
    end

  

保存代碼並運行

..............

嗯,什麼都沒加載出來。

好吧,我得認可,在學習這個框架的過程當中,每走一步都是坑。

我就是在艱難的趟過這些坑來以後,才以爲有必要將這個過程記錄下來,纔有了這一系列文章,但願對後來人有所幫助。

.............

爲何咱們本身的建立的面板沒有加載呢?

查看日誌發現,在"LuaFramework InitOK--->>>"日誌輸出以前,PromptCtrl.New和MessageCtrl.New都被調用了一次,而咱們新加的FirstCtrl卻沒有,見圖3-2。

圖3-2

 應該是咱們某些地方少加了調用。

查找後發現,確實有這樣一個地方。在Lua/Logic/CtrlManager.lua腳本的Init方法,對全部Ctrl的New方法進行了調用。

咱們添加對FirstCtrl.New的調用,以下:

function CtrlManager.Init()
    logWarn("CtrlManager.Init----->>>");
    ctrlList[CtrlNames.Prompt] = PromptCtrl.New();
    ctrlList[CtrlNames.Message] = MessageCtrl.New();
    ctrlList[CtrlNames.First] = FirstCtrl.New(); return this;
end

 (其實第二節中咱們發現了這個地方,本節中忘了將本身的代碼加進去)

 

 而後再運行

.....

報錯了,說咱們的FirstCtrl是一個nil value, 見圖3-3

圖3-3

經查,是在CtrlManager中,咱們沒有加載對應的腳本,見圖3-4(圖中是已添加以後的)

圖3-4

再次運行

出現了更多的錯誤,見圖3-5

圖3-5

 ......

有沒有想崩潰的感受,唉,我當初就是這麼一步步過來的。

此次的錯誤是缺乏first.unity3d.

這裏的緣由是,咱們以前剛把Lua代碼AssetBundle模式關掉(設置爲false),lua代碼不用AssetBundle模式了,但咱們的資源(FirstPanel預製體)還 是使用的AssetBundle模式。

而且資源的AssetBundle模式好像沒法關閉,所以須要對FirstPanel預製體進行打包操做。

操做以下:

一、找到LuaFramework/Editor/Packager.cs文件中的HandleExampleBundle方法(約160行左右),添加對FirstPanel預製體打包的代碼,包名爲"first",以下所示:

 

    /// <summary>
    /// 處理框架實例包
    /// </summary>
    static void HandleExampleBundle() {
        string resPath = AppDataPath + "/" + AppConst.AssetDir + "/";
        if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath);

        AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt");
        AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message");

        //打包咱們新加的FirstPanel預製體
        AddBuildMap("first" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/FirstTest");

        AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt");
        AddBuildMap("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared");
    }

 

二、執行unity編輯器上方LuaFramework菜單中的Build Windows Resources菜單項,進行打包操做。打包完成後,能夠在StreamingAssets目錄中看到first.unity3d文件。見圖3-6

圖3-6

 

再次運行,

此次終於獲得了咱們想要的結果,咱們本身建立的面板FirstPanel,就這麼加載出來了。

見圖3-7

圖3-7

 

真是太不容易了!

 

如今,將咱們改錯的通過都加入到完整的步驟中,那麼,加載一個咱們本身建立的面板的完整步驟以下:

一、建立一個XxxPanel預製體

二、建立對應的XxxView

三、建立對應的XxxCtrl

四、添加CtrlNames及PanelNames

五、在CtrlManager中加入對XxxCtrl.New的調用,並在頭部require "XxxCtrl"

六、在Packager.cs文件中對XxxPanel預製體進行打包

七、在Game.lua加載XxxCtrl

 

 後續寫模塊的時候都會按這個流程來。

 

後記 

在本篇文章的第二節的寫做過程當中,爲何我會用推測並驗證的寫法,而不是直接給出一個正確結論?第三節中,我爲何沒有直接給出正確的操做步驟,而是邊走邊改錯?

由於我但願本文能如實還原我學LuaFramework的過程,記錄每個問題的發生條件,以及我解決問題的思路。

 下一篇文章將會介紹如何加載非XXXPanel的預製體以及按鈕事件處理。

相關文章
相關標籤/搜索