之前写过一篇xLua使用时的注意事项, 今天这篇日志想记录一下自己当时集成xLua时的一些问题,原因是之后我想去学习另一个热更框架:ILRuntime,而一般一个项目集成的工作只需要最开始做一遍,一旦项目忙碌起来,更多时候都是使用自己集成好的功能,而容易忘记当初集成时的做法以及遇到的问题和解决的办法,故此觉得有必要在此记录一下留给自己日后查看,而正是由于以自己记录为主,所以这篇日志可能没有那么强的条理性。
xLua下载完放入自己工程以后,就可以开始进行自己的项目的lua架构设计,其中比较重要的类是LuaEnv,这个可以理解为一个Lua运行环境,他可以创建多个,但是通常来说,我们只需要创建一个就可以了,也就是最好设计成一个全局唯一的变量。在lua里只存在一个结构,就是表:table,所以LuaEnv有一个方法NewTable()就是用来创建一个表,以在用xlua做一个类似MonoBehaviour为例,通常是像下面这样,在一个Unity的MonoBehaviour里面:
private Action luaStart;
private Action luaUpdate;
scriptEnv = luaEnv.NewTable();
LuaTable meta = luaEnv.NewTable();
meta.Set("__index", luaEnv.Global);
scriptEnv.SetMetaTable(meta);
meta.Dispose();
scriptEnv.Set("self", this);
scriptEnv.Get("start", out luaStart);
scriptEnv.Get("update", out luaUpdate);
解释一下,前面两句主要是定义两个Action对象,用来存储从lua脚本那里获取到的start和update函数,,中间那部分就是创建一个新的表,这个表其实就是我们lua文件的表,我称之为脚本环境scriptEnv,它的类型是LuaTable也就是抽象到C#这边的lua表,它有两个比较重要的API就是Get方法和Set方法,Get可以理解为从lua脚本里获取内容,Set可以理解为向这个lua表里填入C#这边的内容,以代码里为例就是相当于创建了一个叫meta的表设置给了scriptEnv的MetaTable作为元表,然后把当前这个C#里的内容(属性和方法)设置到了self这个字段里,那么在lua那边就可以直接通过self.来访问这个C#类里面的内容了,而最后两句Get就是把lua脚本里的start,update方法存到C#这边的luaStart,luaUpdate对象里,这样我们可以在C#这边的Start方法里调用luaStart,就相当于调用了lua脚本的start方法,update方法也类似,来做到让lua脚本模拟一个MonoBehaviour的功能。
另外之前提到的lua运行环境的LuaEnv还有两个重要的方法,一个就是用来执行lua脚本的DoString方法。例如
luaEnv.DoString("local a = 1","main",scriptEnv);
它的三个参数第一个就是要执行的lua脚本代码,第一个是这个代码的chunkname,第三个就是给这个lua代码传入一个table,例如我们之前给scriptEnv设置过self字段,那么我们在对应的lua代码里也就可以使用这个self了。luaEnv的另一个重要API就是AddLoader,用来自定义你的加载lua脚本的逻辑,它需要你传入一个方法,这个方法传入一个文件的名字为参数,需要你返回加载后的lua脚本的byte[]作为返回值,当你掉用lua的require函数时,就会按照你传入的方法去执行加载lua脚本的逻辑,例如:
luaEnv.AddLoader((ref string filename) =>
{
if (File.Exists( filename + ".lua"))
{
return File.ReadAllBytes( filename + ".lua");
}
return null;
});
按照我这个写法就是假如我require一个叫test的lua脚本,那么我就会去当前目录查找名为test.lua的文件,然而实际项目中肯定不会这么写,这要根据你怎么设计自己的脚本存放路径去加载,这里只是举个例子
再有一个注意的地方就是xLua里为你的lua环境集成第三方库,比如常见的json解析库rapidjson,由于我自己写也未必有官方写的好,可以直接参考官方教程:http://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/XLua%E5%A2%9E%E5%8A%A0%E5%88%A0%E9%99%A4%E7%AC%AC%E4%B8%89%E6%96%B9lua%E5%BA%93.md
这个教程就是以添加rapidjson为例,如果还有其他库要添加也可以作为参考。
有了以上几点就基本可以搭建一个完整的热更机制了,剩下的就是根据自己的项目的实际情况去设计了,这个不同的项目都有不同的方案,但原则上一般都会写一套加载lua文件的机制,做好自己的项目文件的路径规划,尤其是最好有一个目录存放本机测试的lua代码,可以用宏定义去做个判断,如果在Editor环境就加载本地lua文件,如果是正式环境再去加载实机存放的目录,通常来说设计完脚本的加载机制,执行的时候最好都从一个main.lua开始执行,由它去同一执行加载你不同的模块,最需要思考的是怎么把你的游戏或者应用的C#逻辑抽象到lua层,这就需要做好Unity这边的模块划分了。不同项目不同,根据项目需要拆分和抽象逻辑即可。
以上是我记录当时给我们项目添加xlua的一些经验,之后去学习ILRuntime的热更框架,等到实际用的差不多了也可能会写一篇博客来分享学习经验,但初步看ILRuntime的中文文档非常详细,而且学习它的一个原因就是因为它可以只用专注C#一个语言来实现热更,这样就避免了要求团队里的人员都必须同时掌握lua和C#的弊端,其实最希望的还是Unity官方自己能出一套热更框架,这样也好统一,不然现在市面上的热更框架实在太多,我也是抱着多学点东西的想法,在不同项目想尝试一些新的东西。