xLua学习之路(二) ------ 通过xLua 虚拟机运行lua程序(包括lua代码/lua脚本)
首先学习下LuaEnv类(Lua虚拟机,建议全局唯一)object[] DoString(string chunk, string chunkName = "chuck", LuaTable env = null)描述:
执行一个代码块。
参数:
chunk: Lua代码;
chunkName: 发生error时的debug显示信息中使用,指明某某代码块的某行错误;
env :为这个代码块;
返回值:
代码块里return语句的返回值;
比如:return 1, “hello”,DoString返回将包含两个object, 一个是double类型的1, 一个是string类型的“hello”
例子:
LuaEnv luaenv = new LuaEnv();
object[] ret = luaenv.DoString("print(‘hello’)\r\nreturn 1")
UnityEngine.Debug.Log("ret="+ret);
luaenv.Dispose()
T LoadString<T>(string chunk, string chunkName = "chunk", LuaTable env = null)
描述:
加载一个代码块,但不执行,只返回类型可以指定为一个delegate或者一个LuaFunction
参数:
chunk: Lua代码;
chunkName: 发生error时的debug显示信息中使用,指明某某代码块的某行错误;
env :为这个代码块;
返回值:
代表该代码块的delegate或者LuaFunction类;
LuaTable Global;
描述:
代表lua全局环境的LuaTable
void Tick()
描述:
清除Lua的未手动释放的LuaBase(比如,LuaTable, LuaFunction),以及其它一些事情。
需要定期调用,比如在MonoBehaviour的Update中调用。
void AddLoader(CustomLoader loader)
描述:
增加一个自定义loader
参数:
loader:就一个回调,其类型为delegate byte[] CustomLoader(ref string filepath),当一个文件被require时,这个loader会被回调,其参数是require的参数,如果该loader找到文件,可以将其读进内存,返回一个byte数组。如果需要支持调试的话,而filepath要设置成IDE能找到的路径(相对或者绝对都可以)
void Dispose()
描述:
Dispose该LuaEnv。
LuaEnv的使用建议:全局就一个实例,并在Update中调用GC方法,完全不需要时调用Dispose示例代码:执行字符串
using UnityEngine;
using XLua;
public class HelloWorld01 : MonoBehaviour {
private LuaEnv luaenv;
// Use this for initialization
void Start () {
luaenv = new LuaEnv();
luaenv.DoString("print('Hello world!')");//参数是lua程序,注意参数既要符合C#的语法规范(传字符串要加“”),又要符合lua语法规范
luaenv.DoString(" CS.UnityEngine.Debug.Log('Hello world') "); //在Lua代码中调用C#代码,要有CS标识
}
/// <summary>
/// 用完要记得释放
/// </summary>
private void OnDestroy()
{
luaenv.Dispose();
}
}
2.从Lua源文件中读取Lua代码并运行
结构如下图:
首先创建Lua文件夹,并加上一个.txt后缀更改成文本格式,比如helloworld.lua.txt(注意后面的.txt):print("Hello world from file")
a=2
b=3
print(a+b) 读取并运行文件中的Lua代码:
TextAsset ta = Resources.Load<TextAsset>("helloworld.lua"); // 加载 helloworld.lua.txt文本,注意加载.lua文件要加后缀
LuaEnv env = new LuaEnv();
env.DoString(ta.text);
env.Dispose();3.通过内置的Loader加载lua源文件
用lua的require函数即可require实际上是调一个个的loader去加载,有一个成功就不再往下尝试,全失败则报文件找不到。目前xLua除了原生的loader外,还添加了从Resource加载的loader,需要注意的是因为Resource只支持有限的后缀,放Resources下的lua文件得加上txt后缀。建议的加载Lua脚本方式是:整个程序就一个DoString("require 'main'"),然后在main.lua加载其它脚本(类似lua脚本的命令行执行:lua main.lua)。
LuaEnv env = new LuaEnv();
//引入并执行Lua代码,是使用loader来加载helloworld.lua.txt,找到就会执行代码,没找到就会报错
//要确保文件在Resources文件夹下,并保证文件名一致
env.DoString("require 'helloworld'");
env.Dispose();loader没有找到文件所报的错误:
4.自定义Loader
当lua脚本放在自定义目录下时使用内置loader时找不到的,因此需要自定义loader
[*]在xLua加自定义loader是很简单的,只涉及到一个接口:public delegate byte[] CustomLoader(ref string filepath);
public void LuaEnv.AddLoader(CustomLoader loader)
通过AddLoader可以注册个回调,该回调参数是字符串,lua代码里头调用require时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把filepath修改为真实路径传出。该回调返回值是一个byte数组,如果为空表示该loader找不到,否则则为lua文件的内容。有了这个就简单了,用IIPS的IFS?没问题。写个loader调用IIPS的接口读文件内容即可。文件已经加密?没问题,自己写loader读取文件解密后返回即可
示例代码:using UnityEngine;
using XLua;
using System.IO;
public class CreateLoader : MonoBehaviour {
void Start () {
LuaEnv env = new LuaEnv();
env.AddLoader(MyLoader);//参数是委托的方法名,其实是自定义方法
//require时会将名字传递给每个loader查找,先执行我们自定义的loader,如果自定义loader返回不为空,则执行改代码,不会再执行内置的loader
env.DoString("require 'test007'");
env.Dispose();
}
private byte[] MyLoader(ref string filePath)
{
string absPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
}
}
页:
[1]