1. 程式人生 > 實用技巧 >toLua與Xlua使用方法總結

toLua與Xlua使用方法總結

兩者都是常見的基於Unity的熱更需求開發出來成熟方案。 實現原理是在Unity啟動後加載一個lua虛擬機器。解釋lua指令碼。再通過各種方法支援C# <> lua 層的互相呼叫。委託。反射。傳值傳址呼叫。

本處只作為初學者對比一下雙方在上手和使用時候的一些異同。以兩種方法實現的跳一跳小遊戲為例。

一 lua配置和exaple示例

1. tolua

2 xlua

二 lua Wrap檔案生成方法

1 tolua 根據配置檔案CustomSetting 指定相關的輸出目錄 需要註冊委託的類。事件。型別等

2 xlua 3種方式進行配置。

1) 使用標籤[CSharpCallLua] / [LuaCallCSharp] 自動識別 對應的類和方法 。

2) 靜態配置檔案 統一配置

3) 動態配置

三 lua啟動環境和C#呼叫lua

1 tolua 全域性統一的LuaClient。

直接載入lua檔案.使用*.lua檔案

public class LuaManager : MonoBehaviour {

    private static LuaManager _instance;
    public static LuaManager Instance{
        get{
            return _instance;
        }
    }

    private LuaClient _luaClient;
    
public LuaClient LuaClient { get { return _luaClient; } } // Use this for initialization void Awake () { _instance = this; DontDestroyOnLoad(this.gameObject); _luaClient = this.gameObject.AddComponent<LuaClient>(); } }
//使用DoFile呼叫lua,使用CallFunc呼叫lua函式
LuaManager.Instance.LuaClient.luaState.DoFile("Login.lua"); LuaManager.Instance.LuaClient.CallFunc("Login.Awake", this.gameObject);

2 xlua 也是初始化1個luaenv後。為每個behavior建立一個獨立環境,防止lua全域性變數汙染。

將lua物件和函式以action方式來呼叫

xlua是通過ReadAllText 或者TextAsset 讀取txt的檔案流。使用 *.lua.txt檔案

 internal static LuaEnv luaEnv = new LuaEnv();//all ua behaviour shared one luaenv only!
        void Awake()
        {
            scriptEnv = luaEnv.NewTable();

            // 為每個指令碼設定一個獨立的環境,可一定程度上防止指令碼間全域性變數、函式衝突
            LuaTable meta = luaEnv.NewTable();
            meta.Set("__index", luaEnv.Global);
            scriptEnv.SetMetaTable(meta);
            meta.Dispose();

            //繫結gameobject物件
            scriptEnv.Set("self", this);
            //使用injection name/object 注入其他Unity物件 交給lua直接引用
            foreach (var injection in injections)
            {
                scriptEnv.Set(injection.name, injection.value);               

            }

            //scriptEnv 賦值 LuaTestScript 指令碼
            luaEnv.DoString("require('Main')");//luarequire
            luaEnv.DoString("require('Continue')");//luarequire
            luaEnv.DoString(luaScript.text, "player", scriptEnv);

            //lua方法 繫結到Action
            luaAwake = scriptEnv.Get<Action<GameObject>>("awake");
            scriptEnv.Get("start", out luaStart);
            scriptEnv.Get("update", out luaUpdate);
            scriptEnv.Get("ondestroy", out luaOnDestroy);
            scriptEnv.Get("onCollisionStay", out onCollisionStay);

            //UnityEngine.SceneManagement.SceneManager.LoadScene("Login");

            if (luaAwake != null)
            {
                luaAwake(gameObject);
            }
        }

四 lua呼叫C#和Unity元件

1 tolua 在啟動main函式中初始化全域性引數

--主入口函式。從這裡開始lua邏輯
--這裡定義我們所需的全域性方法
function Main()
    GameObject = UnityEngine.GameObject
    Transform = UnityEngine.Transform
    ParticleSystem = UnityEngine.ParticleSystem
    Color = UnityEngine.Color
    Util = Util.New()
    SceneManagement = UnityEngine.SceneManagement
    Input = UnityEngine.Input
    KeyCode = UnityEngine.KeyCode
    Time = UnityEngine.Time
    Camera = UnityEngine.Camera
    AudioSource = UnityEngine.AudioSource
    Resources = UnityEngine.Resources
    www = UnityEngine.WWW
    boxCount=0    
    print("logic start")    
end

--場景切換通知
function OnLevelWasLoaded(level)
    collectgarbage("collect")
    Time.timeSinceLevelLoad = 0
end

function OnApplicationQuit()
end

每個lua檔案通過一個table包裝成一個類

Continue = {}
local this = Continue
function this.ReStart(obj)
    local reStartBtn = obj.transform : Find("ReStart").gameObject
    UIEvent.AddButtonOnClick(reStartBtn, ReStartOnClick)
end

function ReStartOnClick ()
    SceneManagement.SceneManager.LoadScene("Jump")
end

2 xlua 使用CS.名稱空間.類名.方法 引用被標籤[LuaCallCSharp]的類和方法

--主入口函式。從這裡開始lua邏輯
--這裡定義我們所需的全域性方法
GameObject = CS.UnityEngine.GameObject
Transform = CS.UnityEngine.Transform
ParticleSystem = CS.UnityEngine.ParticleSystem
Color = CS.UnityEngine.Color
SceneManagement = CS.UnityEngine.SceneManagement
Input = CS.UnityEngine.Input
KeyCode = CS.UnityEngine.KeyCode
Time = CS.UnityEngine.Time
Camera = CS.UnityEngine.Camera
AudioSource = CS.UnityEngine.AudioSource
Resources = CS.UnityEngine.Resources
www = CS.UnityEngine.WWW
Vector3 = CS.UnityEngine.Vector3
Util = CS.XLuaTest.Util
boxCount=0    
local Util
local LuaBoxControl
--local ParticleSystem = UnityEngine.ParticleSystem
function awake(obj)
    print("awake")
    Time.timeScale = 1    
    player = obj
    ui = player.transform : Find('UI').gameObject
    head = player.transform : Find('Head').gameObject
    body = player.transform : Find('Body').gameObject
    rigidbody = player : GetComponent('Rigidbody')
    particle = GameObject.Find('Particle')
    particle : GetComponent('ParticleSystem') : Stop()
    --相機相對角色位置
    cameraRelativePosition = Camera.main.transform.position - player.transform.position
    --呼叫C#類    
    LuaBoxControl = CS.XLuaTest.LuaBoxControl    
end

五 效能效率測試

引用大佬技術貼

Unity中SLua、Tolua、XLua和ILRuntime效率評測