Xlua中LuaBehaviour的實現

簡介

  在基於lua進行熱更新的項目中,我們通常會通過luaBehaviour來讓lua文件模擬MonoBehaviour,可以讓lua文件擁有一些MonoBehaviour的生命周期,如Enable、Disable、Update。
  同時可以注入一些UnityEngine.Object。在lua中方便的調用Unity中的對象。方便開發者進行開發。
  本文進行介紹的luaBehaviour就是基於這個思路設計的,除了上面提到的特性之外還通過Json支援了更多類型的注入,Editor介面更人性化的展示,整個開發過程更接近MonoBehaviour的開發體驗。

使用

1.新建繼承LuaBehaviour的lua文件,通過AddDefineList添加需要序列化的資訊。

2.直接把這個lua文件拖到CS中的LuaBehaviour上即可。


  接下來可以像MonoBehaviour一樣對數據進行編輯了。

實現

腳本的序列化

  luaBehaviour在使用的時候一般是通過記錄名字或路徑的方式來序列化lua文件的的。打包後通過這個路徑從AssetBundle中進行lua文件的載入(這個是lua腳本熱更新常用的策略,在這邊就不多說了)。
  這裡還是通過路徑來記錄lua文件,但是不需要手動輸入,而是通過直接拖動的方式間接記錄lua文件路徑。

注入的方式

  不通過C#側定義註冊資訊,而是通過在Lua中先定義好要註冊的類型和名稱(更符合MonoBehaviour的開發姿勢)。開發時,Editor讀取lua中定義的類型和名稱資訊,展示在Inspector中,供開發者編輯。
  在運行時再將序列化的數據注入到lua實例中。

序列化的實現

UnityEngine.Object類型對象的序列化

  這種類型沒啥特別的,在LuaBehaviour腳本中定義一個記錄key和UnityEngine.Object的List即可。

其他類型的序列化

  非UnityEngine.Object類型就沒有一個統一的格式,無法通過一個列表簡單的進行記錄。但是我們查看Prefab的實例可以發現,Prefab序列化的數據其實和Json很像。對在MonoBehaviour中定義的各個欄位的序列化姿勢也和Json很像。

  所以這裡考慮使用Json來序列化非UnityEngine.Object類型的對象。剛好Unity由提供了一套簡單高效的Json工具JsonUtility。JsonUtility內部就是通過Unity serializer實現的,所以穩定性很有保證。
  但是JsonUtility有個缺點,只能序列化一部分類型,不能序列化如Int、List這種類型。
  為了解決這個問題。這裡在序列化的時候通過泛型為每個類型生成一個Wrap類型。即可通用的實現各種類型的序列化。

注入的實現

UnityEngine.Object類型對象的注入

  也沒啥好說的,直接根據key向Lua實例中Set即可。

其他類型的注入

  先實例化為Wrap對象,然後再取出其中的需要注入的對象,Set到Lua對象中即可。

Inspector介面中的展示

UnityEngine.Object類型對象的展示

  UnityEngine.Object類型統一使用EditorGUILayout.ObjectField繪製即可。

其他類型的展示

  因為沒有找到一個通用的可以表現所有對象的繪製方式,所以這裡也做了一個轉換。先通過Emit生成一個繼承自ScriptableObject的類(因為ScriptableObject是UntiyEngine.Object,所以可以使用SerializedObject來繪製。同時可以直接通過ScriptableObject.CreateInstance進行實例的創建)。把需要繪製的對象放到這個類裡面,然後通過EditorGUILayout.PropertyField繪製即可。

Enable、Update等函數的調用

  這裡把Update、FixedUpdate等高頻或者很少使用的函數拆分出去,只有在Lua中定義了這些函數,才添加對應的Assistant腳本對這些函數進行調用。

  Enable、Disable、Destroy這三個常用函數,就直接放在LuaBehaviour腳本中進行調用。

Tips

  1. 這篇文章只起到大致思路和關鍵點的說明,具體細節可以直接看程式碼,程式碼比較少也比較清晰。
  2. 通過Wrap的方式序列化各種對象的方式其實也可以考慮用到一些用戶數據在客戶端的持久化。
  3. 因為這邊主要展示LuaBehanviour的功能,所以AssetBundle的生成和從AssetBundle中載入lua文件都寫得很臨時,僅作展示用。
  4. 打包測試之前要用AssetBundles->Build AssetBundle For Lua生成一下bundle。

項目鏈接://github.com/blueberryzzz/LuaBehaviour