Unity3D熱更新之LuaFramework篇[09]--資源熱更新與程式碼熱更新的具體實現
前言
在上一篇文章 Unity3D熱更新之LuaFramework篇[08]--熱更新原理及熱更伺服器搭建 中,我介紹了熱更新的基本原理,並且著手搭建一臺伺服器。
本篇就做一個實戰練習,真正的來實現熱更新功能。
一、準備工作
1、製作一個用於熱更新的介面
此前我製作了一個大廳介面,並且放置了兩個按鈕:”排行榜“和”商城“,排行榜按鈕已經用於開啟排行榜頁面。
所以,現在再製作一個商店頁面,當點選商城按鈕的時候,開啟商店頁面。
1) 製作ShopPanel介面。
a) 製作一個商店介面ShopPanel,介面上放一個標題和簡單的3個商品項。如下圖:
b)將ShopPanel做成預製體,放在Assets\LuaFramework\CustomPrj\Shop目錄下。
c)建立ShopPalel.lua和ShopCtrl.lua並做CtrlNames註冊和PanelNames註冊。ShopPanel.lua放在Assets\LuaFramework\Lua\View\Shop目錄下,ShopCtrl.lua放在Assets\LuaFramework\Lua\Controller\Shop目錄下。
d)在Packager.cs的HandleExampleBundle方法中新增打包ShopPanel的程式碼;
//打包準備測試用的ShopPanel預製體 AddBuildMap("shop" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/Shop");
2) 點選商城按鈕顯示商店面板
a) 在HallPanel.lua中新增對商城按鈕的引用;
local transform; local gameObject; HallPanel = {}; local this = HallPanel; --啟動事件-- function HallPanel.Awake(obj) gameObject = obj; transform = obj.transform; this.InitPanel(); logWarn("Awake lua--->>"..gameObject.name); end --初始化面板-- function HallPanel.InitPanel() logWarn("我是HallPanel,我被載入了."); --排行榜按鈕 HallPanel.rankingBtn = transform:FindChild("BtnRanking").gameObject; --排行榜面板 HallPanel.rankingPanel = transform.parent:Find("RankingPanel"); --商店按鈕 HallPanel.shopBtn = transform:FindChild("BtnShop").gameObject; --呼叫Ctrl中panel建立完成時的方法 HallCtrl.OnCreate(gameObject); end function HallPanel.OnDestroy() logWarn("OnDestroy---->>>"); endHallPanel.luab) 在HallCtrl.lua中新增商城按鈕的事件處理
HallCtrl = {}; local this = HallCtrl; local behaviour; local transform; local gameObject; --構建函式-- function HallCtrl.New() logWarn("HallCtrl.New--->>"); return this; end function HallCtrl.Awake() logWarn("HallCtrl.Awake--->>"); logWarn("我是HallCtrl,我被載入了."); end --啟動事件-- function HallCtrl.OnCreate(obj) gameObject = obj; transform = obj.transform; UIEventEx.AddButtonClick(HallPanel.rankingBtn, function () log("你點選了排行榜按鈕"); HallPanel.rankingPanel.gameObject:SetActive (true); end); UIEventEx.AddButtonClick(HallPanel.shopBtn, function () log("你點選了商店按鈕"); --例項化商店面板 local shopCtrl = CtrlManager.GetCtrl(CtrlNames.Shop); shopCtrl:Awake(); end); end --單擊事件-- function HallCtrl.OnClick(go) destroy(gameObject); end --關閉事件-- function HallCtrl.Close() panelMgr:ClosePanel(CtrlNames.Hall); endHallCtrl.lua3) 打包並執行
a) 執行Build Windows Resources操作,新新增的ShopPanel會被自動打進包裡
b) 執行Unity,點選“商城“按鈕,正確地打開了商店面板。
2、修改熱更配置
開啟AppConst.cs指令碼,
將UpdateMode設定為true;
將WebUrl的地址設定為http://192.168.0.110:8080/StreamingAssets/
這個192.168.110是我本機的ip,8080是Tomcat的預設埠號,這裡根據實際情況修改為自己的ip即可。
修改位置見下圖:
3、測試熱更伺服器
1)將Assets下的StreamingAssets目錄整個複製到Tomcat下的webapps目錄,我這裡是
I:\apache-tomcat-9.0.22\webapps。
2)在瀏覽器中輸入http://192.168.0.110:8080/StreamingAssets/files.txt 。
如果能獲取到files.txt的內容,則表明熱更伺服器已經就緒。
二、資源熱更新
1、製作一個客戶端程式
熱更新涉及兩個操作方,一個是伺服器,一個是客戶端。伺服器已經就緒了,現在還缺少一個客戶端程式。
1)首先將unity工程轉換到Android平臺,點選Build Android Resource選單重新生成打包資源。
2)待build完成後,將現在的專案打成一個apk包(注意將Hall場景放在0位置,以便首先載入這個場景)
(打包的時候如果出現報錯說外掛衝突和架構重複啥的,刪掉Plugins目錄下的x86目錄就好,保留x86_64目錄)
3)把StreamingAssets目錄複製到Tomcat的webapps目錄(之前的刪掉就行)。之前測試伺服器的時候拷過去的是Windows版本資源,無法和安卓客戶端進行更新,所以這裡需要重新拷貝。
4)安裝這個apk包到手機,手機應該和電腦位於同一區域網。我這裡使用的是一個安裝在本機上的安卓模擬器。
5)執行剛安裝的程式。
能正常開啟大廳場景,點選商城按鈕,也能正常彈出商店介面。如下圖:
如果剛進遊戲如果直接點選不起作用,等一下再試(正在解壓資源)。
現在客戶端也已經就緒。
2、製作更新內容並上傳到熱更伺服器;
上一步的操作中,我們打了一個安卓包,並將此時的StreamingAssets目錄複製了到了Tomcat中,現在的狀態是:
伺服器上的StreamingAssets內容和安卓客戶的StreamingAssets內容是相同的。這種狀態下客戶端是不會進行更新操作的。
假使安卓包已經上線,過了幾天,我們需要更新版本。
更新內容就是:調整商店頁面的商品,將商品1進行更新。
現在製作一個新的商店頁面。
1)修改ShopPanel的預製體,將原商品1的名稱修改為“新品“,圖示也進行調整,如下圖:
2)執行Build Android Resource選單,重新進行打包;
3)打包完成後,將StreamingAssets目錄複製到Tomcat的webapps目錄下,覆蓋掉之前的內容。
3、重新執行客戶端
經過上一步的操作,現在的伺服器資源是更新後的顯示為“新品”的資源,而客戶而還是之前的顯示為“商品1”的資源。如下圖:
在商店資源更新到伺服器後,不用重新打安卓包。
直接重新執行之前的安卓客戶端 ,如果客戶端開啟商店顯示了“新口”的商品,則說明資源熱更新成功了(預製體是一種Unity資源)。
好了,重新執行客戶端。
點選商城按鈕。能看到,商店介面已經自動更新到伺服器的版本了。
效果與預期的一致,資源熱更成功。
三、程式碼熱更新
這裡說的程式碼熱更,只包含lua程式碼,所有的c#程式碼是沒法更新的。
所以c#程式碼一般用來寫一此底層邏輯,以及通用型邏輯,具體的業務邏輯最好都由lua來實現。
在版本計劃中,如果不得不改動c#程式碼,那就只能發個全量包了。
現在開始做程式碼熱更。
計劃:修改ShopPanel.lua的程式碼,在程式碼中動態修改商店介面的標題,如果能看到商店標題被更改,則表示程式碼熱更成功。
1、 修改ShopPanel.lua的程式碼,在程式碼中引用標題所在的Text元件,並將商店標題修改為“熱更商店”。具體修改見下圖:
2、 點選Build Android Resource,重新生成打包資源;
3、 將StreamingAssets目錄複製到Tomcat的webapps目錄,覆蓋掉之前的;
4、 重新執行客戶端程式。
能看到商店的標題已經被修改了。
說明程式碼更新成功。
至此,熱更操作實戰演練完成。
一些說明:
- 本文選用安卓包做客戶端,一是為了驗證這個熱更功能在移動端上的可用性;二是因為,這個資源熱更功能在Windows平臺無法正常載入更新的資源。可能是框架原因,也可能是我的疏漏,沒有查證。 不過好在安卓平臺上的熱更是沒有問題的。至於iOS平臺,條件有限,沒法去測試。
- 熱更版本的包在第一次啟動的時候,有一個漫長的解壓縮過程,上一篇講原理的時候,有提到過。直接表現就是第一次執行,會黑屏很久。我這裡沒有黑屏,是因為我的大廳面板是直接顯示的,不用等待解壓過程。 但是,一看到大廳介面,就立即點選排行榜按鈕和商城按鈕,是不會在響應的,因為資源未解壓完成,lua指令碼啥的還未載入。 我給工程加了一個Unity-Logs-Viewer外掛,在螢幕上劃2圈,能開啟日誌介面,從日誌裡能看到解壓縮的過程。
- 關於更新,目前框架實現的邏輯也比較簡單,直接比較files.txt的內容,發現不一致就進行更新。 如果是實際專案的話,要做版本控制:Tomcat的webapps目錄下應該是按版本放置的資源,並提供服務端版本號,客戶端要有取服務端版本資訊的能力,並根據版本號,從不同的目錄讀取資源。
- 關於下載,目前的下載邏輯也比較簡易,是按資源一定能下載成功做的邏輯,沒有處理資源下載失敗等異常情況,最好在UI上也能對此過程有顯示,這個需要自己完善。
- 總的來說,這是一個可用的框架,但是還需要自己完善。
專案地址
為方便參照學習,本專案原始碼已經上傳到github,地址:
https://github.com/tanyuqing/LuaFramework-in-action