一、XLua背景
xLua是Unity3D下Lua编程解决方案,自2016年初推广以来,已经应用于十多款腾讯自研游戏,因其良好性能、易用性、扩展性而广受好评。现在,腾讯已经将xLua开源到GitHub。想了解的,可以点击这里Xlua下载。
二、在Unity中导入XLua
首先,将上述的Xlua ZIP下载下来,然后打开xLua-master.zip包,你会看到一个Assets目录,这目录就对应Unity工程的Assets目录,保持这目录结构放到你的Unity工程即可。显然,这与导入一个Unity插件很类似。导入成功后,你的菜单栏里面会多一个XLua的功能。
三、Unity中加载Lua文件
Unity有两种方式加载Lua文件:1.使用Unity动态加载的方式获取lua文件 2.用lua的require函数。
首先,将要读取的Lua文件(比如:test.lua)放在Resources文件夹下(没有Resources文件夹的话,就自己创建一个);然后,将要读取的Lua文件的后缀名修改为(比如:test.lua.txt)。此处一定要修改成txt结尾的,否则就会读取不出来。(后面会进行解释);最后,在Unity创建脚本文件HelloWorldTest.cs,代码示例如下:
using UnityEngine;
using XLua;
public class HelloWorldTest : MonoBehaviour {
//通过字符串的方式加载lua文件
void Start () {
LuaEnv env = new LuaEnv();//创建一个lua虚拟机
//第一种 使用Unity动态加载的方式获取lua文件
Debug.Log("第一种加载方式:");
TextAsset ta = Resources.Load<TextAsset>("test.lua");
env.DoString(ta.ToString());
//第二种
//使用lua的require函数来获取lua文件
//require实际上是调一个个的loader去加载
//有一个成功就不再往下尝试,全失败则报文件找不到。
Debug.Log("第二种加载方式:");
env.DoString("require 'test'"); //加载test.lua.txt文件
env.Dispose();//释放lua虚拟机
}
}
在采用第一种方式实现,在Unity中获取Lua文件时,采用的是动态加载的方式,指定的类型是TextAsset类型,此时,只能加载后缀为.txt的文件,因此,需要将lua文件的后缀进一步扩展成.txt。第二种,使用使用lua的require函数,用法看上面具体实现实现即可。require实际上是调一个个的loader去加载,下面将介绍一下自定义Loader如何加载Lua文件。
四、自定义Loader(CustomLoader)的实现
在XLua中,提供了一个接口,让我们实现自定义Loader。接口如下:
public delegate byte[] CustomLoader(ref string filepath);
public void LuaEnv.AddLoader(CustomLoader loader)
通过AddLoader可以注册个回调,该回调参数是字符串,lua代码里头调用require时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把filepath修改为真实路径传出。该回调返回值是一个byte数组,如果为空表示该loader找不到,否则则为lua文件的内容。依旧读取上述Resources文件夹下test.lua.txt文件,该文件内容只有一条“print(“Hello World!”)”语句。此时执行的不是Resources文件夹下test.lua.txt文件(Hello World!没有被输出),而是执行了自定义Loader里更新的Lua文件(输出123)。测试示例代码如下:
using UnityEngine;
using XLua;
using System.Text;
public class CustomLoaderTest : MonoBehaviour {
// 自定义loader
void Start() {
LuaEnv env = new LuaEnv();
//添加自定义loader
env.AddLoader(MyCustomLoader);
//当自定义了MyCustomLoader的loader之后,由于更新了lua程序,源lua文件中的语句不被执行;
//因为该loader被找到了,不再继续往下找
env.DoString("require 'test'"); //此时,输出的不是Hello World!,而是123
env.Dispose();
}
//自定义loader
private byte[] MyCustomLoader(ref string filePath)
{
//Debug.Log(filePath); //输出 test
string s = "print(123)"; //更新的lua程序
return Encoding.UTF8.GetBytes(s); //将lua文件转换为Bytes数组进行读取
}
}
另外,再看下,如何使用自定义的Loader加载Lua文件。首先,创建StreamingAssets文件夹,用于存放要读取的lua文件。然后,将lua文件的后缀扩展成.txt(比如:test007.lua.txt)。最后,创建Unity脚本CustomLoadLuaTest.cs,示例代码如下:
using UnityEngine;
using XLua;
using System.Text;
using System.IO;
public class CustomLoadLuaTest : MonoBehaviour {
//通过读取文件的方式加载lua文件
void Start () {
LuaEnv env = new LuaEnv();
//添加自定义loader
env.AddLoader(MyCustomLoader);
env.DoString("require 'test007'"); //输出 Hello World!
env.Dispose();
}
//自定义loader
private byte[] MyCustomLoader(ref string filePath)
{
//第一种:将Lua文件Resources文件加下
//需要将Lua文件的相对路径拼出来
//string path = ".\Assets\Test\Resources\" + filePath + ".lua.txt";
//return Encoding.UTF8.GetBytes(File.ReadAllText(path));
//第二种:将Lua文件放置在StreamingAssets文件夹下
//Application.streamingAssetsPath获取StreamingAssets文件夹的目录地址
string absPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
return Encoding.UTF8.GetBytes(File.ReadAllText(absPath)); //读取lua文件
}
}
因此,若采用自定义Loader加载Lua文件时,优先采用第二种方式来进行获取。