[Unity熱更新]tolua# & LuaFramework(一):基礎

1、tolua#c#

c#調用lua:LuaState[變量名/函數名]

1.LuaState
a.執行lua代碼段
DoString(string)
DoFile(.lua文件名)
Require(.lua文件名(但沒有.lua後綴))

b.獲取lua函數或者表
LuaFunction func = lua.GetFunction(函數名);             或者           LuaFunction func = lua[函數名] as LuaFunction;
LuaTable table = lua.GetTable(表名);

c.Start():若是須要使用wrap,則須要調用該方法數組


2.LuaFunction
Call()


3.LuaTable服務器

LuaTable[變量名/函數名]框架

ToArray()ide


lua調用c#
函數

在c#中將引用傳遞到lua中後:工具

1.經過「.」 (點號)來使用非靜態的變量以及靜態的變量與方法oop

2.經過'':「 (冒號)來使用非靜態的方法ui

3.經過"{}"來傳遞數組給c#this

4.建立GameObject:newObject(變量)

5.摧毀GameObject:destroy(變量) 

6.獲取組件:GetComponent('LuaBehaviour')


2、LuaFramework(使用PureMVC)

a.基礎模塊

1.Util:對Mono的功能進行封裝,這樣不繼承Mono的類就能使用Mono的東西了(如transform.Find、GetComponent);還有其餘的工具方法

2.AppFacade:繼承Facade,整套框架的入口

3.Base:繼承MonoBehaviour,是一切View和Manager的基類;持有各類Manager的引用;能註冊移除(view所感興趣的)信息

4.View:只有一個方法:public virtual void OnMessage(IMessage message) 這是處理信息的方法

5.Manager:繼承Base

6.AppView:繼承View,是一個範例:註冊View所感興趣的信息,處理信息


b.lua模塊

1.LuaFileUtils:經過.lua文件路徑和AssetBundle文件路徑這兩種方式來找.lua文件,並讀取返回byte[]

2.LuaLoader:繼承LuaFileUtils,並沒有重要變化

3.LuaEvent:相似c#中的event,提供Add和Remove方法

4.LuaLooper:繼承MonoBehaviour,在Update / LateUpdate / FixedUpdate中執行對應的LuaEvent

5.LuaBinder:若是執行的.lua文件須要用到unity中的類型,則須要用這個類給LuaState進行綁定

6.LuaManager:繼承Manager,入口類,初始化Lua代碼加載路徑(調試模式下是在Assets \ LuaFramework目錄下,非調試模式是在C:\luaframework\lua(window系統),默認是非調試模式),引用一個LuaState並封裝其功能(讀取lua文件、調用方法等)

7.LuaBehaviour:繼承View,在Awake / Start中調用lua中對應的方法;並提供點擊事件的相關處理


c.Manager模塊

1.ResourceManager:加載AssetBundle的相關操做。在pc平臺上默認加載的是Assets\StreamingAssets裏的東西,移動平臺上則是Application.persistentDataPath。那麼若是咱們想在pc平臺上像移動平臺同樣讀取外部路徑(使用www),在pc平臺模擬熱更新,那麼就能夠在Initialize這個方法修改:m_BaseDownloadingURL = "file:///" + Util.DataPath;


unity5加載AB包的四個步驟:

a.爲assetbundle起名字,並打包

b.加載總的清單文件

c.加載assetbundle的依賴文件

d.加載assetbundle


m_Dependencies:key爲AB包的名字,value爲依賴的AB包的名字

m_LoadedAssetBundles:key爲AB包的名字,value爲加載後的AB包

m_LoadRequests:key爲AB包的名字,value爲對包內資源的請求


先經過Initialize方法加載總的清單文件,而後咱們能夠經過LoadPrefab方法來加載AB包,此時會把對這個AB包的請求放在m_LoadRequests中,而後在OnLoadAsset方法對該AB包的全部請求進行處理,經過GetLoadedAssetBundle方法看看內存中有沒有這個AB包,若是有的話,再檢查一下該AB包的依賴包是否也在內存中,若是都在,就把請求的包內資源加載出來,並回調方法。若是出現缺包狀況,會經過OnLoadAssetBundle方法加載AB包及其依賴包(使用遞歸)。

至於卸載AB包,使用的是UnloadAssetBundle方法。這裏還有說一下引用計數的問題,例若有A1A2A3三個包,A2A3依賴A1,而後咱們加載A2A3。那麼A1的引用計數爲2,A2的引用計數爲1,A3的引用計數爲1,當使用UnloadAssetBundle卸載掉A2包時,A1的引用計數變爲1,此時還會留在內存中,再卸載A3包,A1的引用計數變爲0,A1包就自動被卸載了。包被加載一次,則引用計數加1,因此上面的A2A3包引用計數爲1,;包被依賴一次,則引用計數加1,因此上面的A1包引用計數爲2,;每次卸載時計數減1,減到0則從內存中去掉。


2.PanelManager:默認lua建立的panel都要在tag爲GuiCamera的物體下,提供建立panel的方法

3.ThreadManager:解包與下載資源


lua代碼分析:

PromptPanel.lua

1.函數是能夠存儲在變量中的。函數與其餘全部值都是匿名的,即它們都沒有名稱。當討論一個函數名時,其實是在討論一個持有某函數的變量。

[csharp]  view plain  copy
  在CODE上查看代碼片 派生到個人代碼片
  1. a = {p = print}    
  2. a.p("hello woeld")     --hello woeld    
  3. print = math.sin    
  4. a.p(print(3.14159))    --約等於0    
  5. sin = a.p    
  6. sin(10,20)             --10 20    
因此對於:function foo(x) return 2*x end                                             其實就是等於:foo = function (x) return 2*x end
那麼對於:function PromptPanel.Awake(obj)  xxx end                     其實就是等於:PromptPanel.Awake = function (obj)  xxx end


2.引用table

[csharp]  view plain  copy
  在CODE上查看代碼片 派生到個人代碼片
  1. a = {}                --建立一個table,並將它的引用存儲到a    
  2. a["x"] = 10    
  3. b = a                 --b與a引用了同一個table    
  4.     
  5. print(b["x"])         --10    
  6. b["x"] = 20    
  7. print(a["x"])         --20    
  8. a = nil               --如今只有b還在引用table    
  9. b = nil               --再也沒有對table的引用了    



3.

[csharp]  view plain  copy
  在CODE上查看代碼片 派生到個人代碼片
  1. a = {}    
  2. x = "y"    
  3. a[x] = 10    
  4. print(a[x])    --10    
  5. print(a.x)     --nil    
  6. print(a.y)     --10    
  7.     
  8. --a.x等同於a["x"]   
那麼,對於上面的PromptPanel.Awake,就是等於PromptPanel["Awake"]


PromptCtrl.lua

1.對於沒有local聲明的變量均爲全局變量,能夠在其餘.lua文件中調用

2.在Common/define.lua中註冊View、Controller,define.lua中持有各類manager的引用


PromptPanel & PromptCtrl:PromptPanel維護了面板的控件變量,提供給PromptCtrl使用,沒有model層是由於沒有數據

CtrlManager:管理controller層,維護全部的controller

Game:在OnInitOK方法中指定開始的panel,例如例子中的:local ctrl = CtrlManager.GetCtrl(CtrlNames.Prompt);


總結

1.對於一個panel,須要添加或修改的文件:

a.添加xxxPanel & xxxCtrl

b.修改define、Game、CtrlManager

詳細的可見:http://blog.csdn.net/adambieber/article/details/47402805


2.在lua中使用AB包內的資源的兩種方法:

a.panelMgr:CreatePanel('Prompt', this.OnCreate);

b.resMgr:LoadPrefab('prompt', { 'PromptItem' }, this.InitPanel);

其中a是對b的進一步封裝,所以二者都須要提供AB包名、要訪問的包內資源名字(若是是panel,則默認資源名爲AB包名+"Panel")以及回調方法(參數是AB包中的資源)


3.熱更新的四個步驟:打包、解包、更新和加載。而這四個步驟框架已經給咱們封裝好了,基本上就不須要咱們去管了,但仍是頗有必要理解其中的過程。

a.打包:將資源所有打包到StreamingAssets文件夾

打包類:LuaFramework / Editor / Packager 

打包lua文件:HandleLuaBundle,對Assets\LuaFramework\Lua 與 Assets\LuaFramework\ToLua\Lua這兩個目錄下的全部lua文件進行打包

打包圖片等資源:HandleExampleBundle


b.解包:在移動端StreamingAssets這個文件夾是隻讀的,可是要作熱跟新的話,就須要寫入文件,所以Application.persistentDataPath這個可讀可寫的路徑纔是數據在移動端的存放路徑,同時也爲了比較MD5的值,就須要將StreamingAssets的東西解包(複製)到Application.persistentDataPath


c.更新:files.txt這個文件記錄了全部的資源文件及其MD5值,每次進入遊戲時都會從服務器下載最新的files.txt,而後對其遍歷比較MD5值,若是值不一樣或者不存在則下載


d.加載:先加載資源的依賴,再加載資源


那麼,若是咱們對外發布了一個版本1.1,而後更改資源,發佈1.2,要作的就是:從新生成apk並上傳,而後將StreamingAssets文件夾下的東西上傳到服務器,具體位置見AppConst.WebUrl;對於用戶來講,若是他安裝的是1.1,那麼就會下載更新,若是他安裝的是1.2,那麼解包以後就獲得最新的資源了,無需更新了。



4.整套框架的工做流程:

c#                                                                                                                                                         

打包好後,啓動遊戲,GameManager會進行一些判斷,若是這是遊戲安裝以後的第一次啓動,那麼就會進行解包操做。若是AppConst.UpdateMode爲false,那麼就不會檢測更新,不然就會進行更新操做。而後進入初始化操做,調用Game.lua中的OnInitOK方法,進入lua邏輯。

lua

而後調用指定控制器的Awake方法、PanelManager的CreatePanel方法,調用c#代碼,建立panel,爲其添加LuaBehaviour,調用xxxPanel.lua的方法,獲取控件引用,進行邏輯處理。


From:http://blog.csdn.net/lyh916/article/details/45021703

相關文章
相關標籤/搜索