1. 程式人生 > >ToLua學習筆記,執行bundle中的lua指令碼

ToLua學習筆記,執行bundle中的lua指令碼

ToLua框架支援直接讀取執行lua指令碼檔案,也支援讀取打包到.unity3d中的lua指令碼。另外ToLua還支援位元組碼方式讀取指令碼。

打包工具類Packager.cs中對指令碼的打包,選擇如下打包方式:


注意此部分經過我的修改。然後它會呼叫下邊部分:



上邊選擇了lua位元組碼方式,其實區別只是EncodeLuaFile函式會把lua指令碼編譯成可被luajit執行的格式檔案。此函式內容如下:


無論是否選擇位元組碼方式,最終生成的到臨時目錄Lua中的檔案都是.byte結尾的。

ToLua/Lua和Lua目錄下的指令碼會拷貝到Lua目錄下

我的工程目錄結構如下:


臨時目錄下的結構如下:


對lua指令碼的打包是把他們所在的資料夾打包,而不是每個lua檔案分別打包,所以在遍歷Lua目錄後,還需要把Lua目錄本身加入打包列表,因為它下邊也包含指令碼.

最終打包到StreamingAssets下的結構如下:


打包完資源後,BuildLuaFile()函式會生成一個luafiles檔案,到StreamingAssets/lua中,內容如下:


BuildLuaFile函式的內容如下:


這個檔案是用來幹啥的呢?我們看一下LuaManager.cs中的程式碼:


此程式碼經過了我的修改,它的目的是讀取luafiles中列出來的所有包含lua指令碼的.unity3d檔案,並加入到loader的字典中:

我們來看下LuaLoader.cs中的程式碼:


此程式碼經過了我的修改,注意上邊轉小寫的目的是因為之前打包的時候,所有資原始檔都被小寫化了。

這裡讀取了所有指令碼的bundle包,並組合了名稱,儲存到字典中,繼續看AddSearchBundle函式:

那什麼時候會使用到它們呢?我們來看LuaManager.cs中的呼叫:


繼續進入:


此處我也做了修改,增加了bundleName引數,為什麼增加這個引數後續會介紹。繼續進入ReadFile


我選擇了bundle方式,所以會執行下邊函式,那上邊的beZip是哪裡設定的呢?看下邊:


繼續進入ReadZipFile:


這裡是最關鍵的地方,只要是有luaState.DoFile的呼叫最終都會執行到這裡

這裡經過了我的修改,框架原來的程式碼只有fileName引數,而我們的資源包是以資料夾為單位的,所以想確定fileName(lua指令碼名)到底屬於哪個資源包是做不到的,

因此才會有原來的那種拼接字串的無奈寫法。

我這裡增加了bundleName引數,在直接呼叫時,可以找到資源包,注意zipMap.TryGetValue這行。

但其實這裡還有個問題,有的時候並不是主動呼叫DoFile才會到這個函式,比如初始化時,後續的子呼叫到達這裡,這個時候bundleName引數是null的,所以我也保留了

原來的那種拼接方式,只是稍作修改,符合我luafiles檔案中的檔名格式。這種方式能執行lua目錄下和lua/fileName目錄下的指令碼。

之前還有個地方執行時也會呼叫這裡:


ReadZipFile返回的是byte[],最終輸入到下邊執行:


這裡lua檔名也就是chunkName(塊名),最終由底層dll呼叫,此時執行例項便可看到main.lua的結果