Unity中使用ulua的個人經驗總結

Lua代碼都是運行時才編譯的,不運行的時候就如同一張圖片、一段音頻一樣,都是文件;所以更新邏輯只需要更新腳本,不需要再編譯,因而Lua能輕鬆實現“熱更新”。Ulua是一款非常實用的unity插件,它能讓unity支持Lua語言,而且運行效率還不錯。下面就跟大家談談我用ulua的一些心得。

Ulua的使用流程一般爲:

實例化LuaState對象(new LuaState())è加載Lua代碼(LuaState. DoString(string))è調用Lua代碼中的方法(GetFunction(string),LuaFunction.callFunction(string))。其中,加載Lua代碼這一塊,可以直接賦一段Lua代碼字符串,也可以指定一個Lua腳本文件。爲了熱更新,應當採用第二種加載方法,即創建一個Lua腳本文件。由於Unity不支持擴展名爲lua的文件,所以可將Lua腳本擴展名定爲txt(純文本文件),並用unity的TextAsset列表負責記錄所有腳本文件。建議列表中給每個腳本搭配一個string類型的ID,這樣憑此ID即可加載正確的lua腳本;另外在LuaState類中新增一個String類型的public成員,賦值爲該ID。這樣一旦某個Lua腳本在運行時報錯,可根據輸出的ID值判斷是哪個Lua腳本有錯誤。

關於Lua裏的預處理:

luanet.load_assembly("Assembly-CSharp")

luanet.load_assembly('UnityEngine')

Vector2 = luanet.import_type('UnityEngine.Vector2')

Vector3 = luanet.import_type('UnityEngine.Vector3')

GameObject = luanet.import_type('UnityEngine.GameObject')

luanet.import_type('System.Collections.Generic.List')

Debug = luanet.import_type('UnityEngine.Debug')

這些都是常用的Lua預處理,建議單獨寫個Lua腳本記錄這些,以後加載其他Lua腳本前都先加載一下這個腳本。自定義C#類也是可以import的,import操作是Lua調用C#的前提。當然在C#中實例化的LuaState也可以預定義一些Lua全局變量,這都是在C#裏完成的,比如:

[code]csharpcode:

void SetLuaData(LuaState lua){       lua["transform"] = transform;       lua["gameObject"] = gameObject;}

預定義了兩個變量,一個是transform,一個是gameObject。

關於Lua裏的全局變量:

Lua裏所有的字符串,如果不是關鍵字或者運算符,就都是變量;這些變量中,凡是沒用local關鍵字修飾的,就是全局變量,反之,則是局部變量。每個LuaState對象,當它加載過Lua代碼以後,它裏面定義的全局變量,在這個對象生命期內是一直存在的。如果兩次調用這個LuaState的某方法,第一次將某全局變量進行了修改,那麼第二次,這個全局變量會在第一次修改的基礎上繼續修改。

關於Lua在Unity的適用範圍:

雖然Lua可以負責Unity工程的任何模塊,但是出於對遊戲性能的考慮,儘量少的低頻率的調用Lua,比如儘量少在Update函數中調用Lua、循環利用已經實例化過的LuaState避免浪費資源。對於那些不需要高效運算的模塊,比如UI部分,就可以放心大膽的使用Lua。

關於Lua與NGUI的適配:

調用Lua的主要方式就是callFunction,而對於NGUI來說,一般都是按鈕觸發某C#腳本的函數,那麼如何用按鈕觸發Lua的函數呢?這就需要有個C#腳本作爲“中介”,這個“中介”需要有自己的LuaState實例,當執行“中介”的某個方法時,由該方法調用callFunction。至於具體調用Lua腳本的哪個方法,可以通過傳參的方式告訴這個“中介”——修改NGUI的ButtonMessage類,加入新的public string LuaFunctionName成員,以後由它來制定要調用的Lua方法名就好了。而通過NGUI的UIButton等調用C#的方法,也是同理的(NGUI3.5.6版以後,可以給UIButton等等組件的觸發方法添加參數了)。

關於Lua與SimpleJSON的適配:

SimpleJSON是一個開源的JSON庫,這個詳見之前的博客。由於Lua語言無法理解C#裏面的屬性,所以凡是SimpleJSON裏的public A{get,set}這種,要新寫一些接口函數返回它們的取值,以供Lua調用。而且Lua調用C#裏經過很多重載的函數,也經常判斷錯誤(這是個bug?),所以乾脆多弄一些函數名,避免調用錯誤。

關於Lua與Lua之間的調用:

在Unity中使用Ulua,想要讓兩個Lua腳本彼此調用是很難的,需要通過C#作爲“中介”,而且Lua不支持C#的泛型,所以不能用GetComponnet<類名>()的形式,只能用GetComponnet (“類名”)的形式去獲取組件。兩個Lua腳本相互傳參也很麻煩,因爲有了C#腳本作爲“中介”,所以不能傳tabel類型的參數,我的做法是將若干參數拼成一個json字符串傳遞過去,另一方再解json包。感覺有點蛋疼。不過這種情況並不多見,都是可以避免的(比如一個模塊只用一個大Lua腳本,各自獨立減少溝通)。

關於Lua編輯器:

個人使用的是notepad++,也有很多人用sublime,代碼摺疊這塊notepad++更好一些,而sublime在功能上貌似更強大一些。

Unity編程的親們,有沒有在Unity運行狀態下修改並保存了腳本,然後切回來Unity直接卡死的慘痛經歷?使用Lua,你將告別這一現象,有木有心動呢?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章