两者都是常见的基于Unity的热更需求开发出来成熟方案。 实现原理是在Unity启动后加载一个lua虚拟机。解释lua脚本。再通过各种方法支持C# <> lua 层的互相调用。委托。反射。传值传址调用。

本处只作为初学者对比一下双方在上手和使用时候的一些异同。以两种方法实现的跳一跳小游戏为例。

一  lua配置和exaple示例

1. tolua

tolua xlua tolua xlua 区别_Source

tolua xlua tolua xlua 区别_lua_02

 

2 xlua 

 

 

tolua xlua tolua xlua 区别_tolua xlua_03

 

 

二 lua Wrap文件生成方法

1 tolua 根据配置文件CustomSetting 指定相关的输出目录 需要注册委托的类。事件。类型等

tolua xlua tolua xlua 区别_Time_04

 

2 xlua 3种方式进行配置。 

1) 使用标签[CSharpCallLua] / [LuaCallCSharp] 自动识别 对应的类和方法 。

2) 静态配置文件 统一配置

3) 动态配置 

tolua xlua tolua xlua 区别_Source_05

 

 

三 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效率评测

 

unity游戏热更新方案比较(xlua tolua)

Lua文件的加载方面。xlua是AddLoader , tolua是AddSearchPath 不过xlua可以通过hotfix对c#中的代码进行修改 主要是方便改bug(简称打补丁)而且官方文档说GC性能问题有很大的提升 tolua不可以对C#中的代码进行修改 但tolua多了AB打包类 以及其他的一些管理类