一、什么是xLua
xLua为Unity、 .Net、 Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用。
xLua是用来实现Lua代码与C#代码相互调用的插件。我们可以借助这个插件来实现热更新方案。
那么为什么要选择Lua实现热更新呢?
这是因为Lua具有轻量、灵活的特点,可以在几乎任何平台上编译、运行。Unity一般使用C#代码编写游戏逻辑。在打包时,C#会先编译成IL(中间语言),存储到dll(动态链接库)中。在游戏运行时,需要通过JIT(即时编译)将IL解释为机器码。在这期间,会开辟一块内存空间,且要求这块空间可读、可写、可执行。但IOS平台是不允许获取具有可执行权限的内存空间的。因此只能进行全量更新。但Lua是使用C写的脚本语言,在运行时读入Lua代码,在解释时直接使用C代码进行解释,不需要开辟特殊的内存空间,执行解释的是C语言编写的虚拟机。(参考自这篇文章)
二、如何使用
2.1 Hello World
首先在xLua的GitHub主页下载源码,并引入到Unity中。
创建一个C#脚本,并编写如下代码。DoString()方法可以执行传入的Lua代码。
public class HelloWorld : MonoBehaviour
{
private LuaEnv _lua;
private void Start()
{
_lua = new LuaEnv();
_lua.DoString("print('Hello World')");
}
private void OnDestroy()
{
_lua.Dispose();
_lua = null;
}
}
将脚本挂载到一个游戏物体上,运行游戏。可以在控制台看到输出结果,且输出的字符串带有“Lua:”前缀。

需要注意的是,一个LuaEnv的实例对应着一个Lua虚拟机,建议全局唯一。
2.2 加载Lua文件
在DoString()方法中直接写大量的Lua代码是不现实的,我们需要载入外部的Lua文件,并将文件内容传入这个方法中执行。
首先编写一个简单的Lua脚本,并将脚本放在「Resources」目录下
a = 2
b = 3
print("a+b="..a+b)
然后在C#脚本中通过Resources进行载入
public class LoadLuaFile : MonoBehaviour
{
private void Start()
{
var lua = Resources.Load<TextAsset>("AddLua");
Debug.Log(lua);
if (lua != null)
{
LuaEnv luaEnv = new();
luaEnv.DoString(lua.text);
luaEnv.Dispose();
}
}
}
此时运行游戏我们会发现,控制台输出的是「Null」。这是因为Resources.Load<TextAsset>()会默认给文件名后面增加「.txt」后缀。也就是说这个方法只会读取到后缀为「.txt」的文件。

为了能读取到Lua文件,我们需要将Lua文件的后缀改为「.lua.txt」。在加载时,文件名传入「XXX.lua」,这样就能顺利读取到Lua脚本的内容了。

我们也可以使用xLua内置的loader进行加载。方法是在luaEnv.DoString()方法中直接传入require语句。require会调一个个的Loader去加载,直到遇到不返回空的Loader。如果全部返回空则会报文件找不到的异常。
LuaEnv luaEnv = new();
luaEnv.DoString("require 'AddLua'");
luaEnv.Dispose();
如果lua脚本没有问题,但运行时“unexpected symbol”之类的错误,可以用记事本打开lua脚本,重新保存为UTF-8编码格式。
2.3 自定义Loader
某些情况下系统内置的Loader并不能满足我们的需求。比如需要对Lua文件解密,或者Lua文件不在「Resources」目录下等。这时就需要我们自定义Loader。
要实现自定义Loader也很简单,只需要调用LuaEnv.AddLoader()方法,添加一个自定义Loader即可。该方法需要传入一个委托,委托的参数是加载文件的路径,返回值是文件内容的字节数组。
public class CustomLoader : MonoBehaviour
{
private void Start()
{
LuaEnv luaEnv = new();
luaEnv.AddLoader(MyLoader);
luaEnv.DoString("require '不存在的文件'");
luaEnv.Dispose();
}
private byte[] MyLoader(ref string filePath)
{
string content = "print('Hello World')";
return System.Text.Encoding.UTF8.GetBytes(content);
}
}
上面的代码运行结果如下

要实现加载指定目录的Lua文件,只需要在自定义Loader中通过文件流读取文件即可
string path = "[指定路径]";
return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
2.4 C#访问Lua
2.4.1 访问全局变量
Lua脚本
str="Hello World"
num=12

本文介绍了xLua插件在Unity中的应用,用于实现C#与Lua代码的相互调用,以实现游戏的热更新功能。通过示例展示了如何加载Lua脚本、访问全局变量和函数,以及如何在Lua中调用C#代码。同时,讨论了自定义Loader和不同方式的C#与Lua交互,包括委托和LuaFunction的使用。
最低0.47元/天 解锁文章
1344

被折叠的 条评论
为什么被折叠?



