xLua学习之路(二) ------ 通过xLua 虚拟机运行lua程序(包括lua代码/lua脚本)

  1. 首先学习下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[0]);
        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));
    }
}


猜你喜欢

转载自blog.csdn.net/dengshunhao/article/details/80534760