两者都是常见的基于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效率评测
unity游戏热更新方案比较(xlua tolua)
Lua文件的加载方面。xlua是AddLoader , tolua是AddSearchPath 不过xlua可以通过hotfix对c#中的代码进行修改 主要是方便改bug(简称打补丁)而且官方文档说GC性能问题有很大的提升 tolua不可以对C#中的代码进行修改 但tolua多了AB打包类 以及其他的一些管理类