Lua文件加载

  1. 执行字符串
    最基本是直接用LuaEnv.DoString执行一个字符串,当然,字符串得符合Lua语法
    比如:
/* C# Code */
using UnityEngine;
using System.Collections;
using XLua;

namespace Tutorial
{
    public class ByString : MonoBehaviour
    {
        LuaEnv luaenv = null;
        // Use this for initialization
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("print('hello world')");
        }

        // void Update()
        // {
        //     if (luaenv != null)
        //     {
        //         luaenv.Tick();
        //     }
        // }

        // void OnDestroy()
        // {
        //     luaenv.Dispose();
        // }
    }
}

但这种方式并不建议,更建议下面介绍这种方法。

  1. 加载Lua文件
    用lua的require函数即可
    比如:
/* C#Code */
using UnityEngine;
using System.Collections;
using XLua;

namespace Tutorial
{
    public class ByFile : MonoBehaviour
    {
        LuaEnv luaenv = null;

        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'byfile'"); // 输出 “hello world”
        }

        // void Update()
        // {
        //     if (luaenv != null)
        //     {
        //         luaenv.Tick();
        //     }
        // }

        // void OnDestroy()
        // {
        //     luaenv.Dispose();
        // }
    }
}
/* LuaCode */
// Resources/byfile.lua.txt
// Resources只支持有限的后缀所以要加个其他后缀,如txt
print('hello world')

require实际上是调一个个的loader去加载,有一个成功就不再往下尝试,全失败则报文件找不到。

目前 xLua 除了原生的 loader 外,还添加了从 Resource 加载的 loader,需要注意的是因为 Resource 只支持有限的后缀,放 Resources 下的 lua 文件得加上 txt 后缀。

建议的加载 Lua 脚本方式是:
整个程序就一个 DoString("require 'main'"),然后在 main.lua 加载其它脚本(效果类似 Lua 脚本的命令行执行: lua main.lua)。

有童鞋会问:
要是我的 Lua 文件是下载回来的,或者某个自定义的文件格式里头解压出来,或者需要解密等等,怎么办?
问得好,xLua 的自定义 Loader 可以满足这些需求。

  1. 自定义 Loader
    在 xLua 加自定义 loader 是很简单的,只涉及到一个接口:
public delegate byte[] CustomLoader(ref string filepath);
    // LuaEnv.AddLoader(CustomLoader loader)

通过 AddLoader 可以注册个回调,该回调参数是字符串,lua 代码里头调用 require 时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件.
如果需要支持调试,需要把 filepath 修改为真实路径传出。该回调返回值是一个 byte 数组,如果为空表示该 loader 找不到,否则则为 lua 文件的内容。

透传消息,就是消息体格式及内容,对于传递的通道来说是不去过问的,通道只负责消息的传递,对消息不做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息。

有了这个就简单了,用 IIPS 的 IFS?
没问题。写个 loader 调用 IIPS 的接口读文件内容即可。文件已经加密?没问题,自己写 loader 读取文件解密后返回即可。。。

完整示例见

/* C# Code */
    using UnityEngine;
    using XLua;


    public class ChangeHelloWorld : MonoBehaviour
    {
        LuaEnv luaEnv = null;
        void Start()
        {
            this.luaEnv = new LuaEnv();
            // 1)使用 LuaEnv 的 AddLoader 添加一个回调函数
            this.luaEnv.AddLoader(this.loadedLua);
            // 2)lua 中用 require 加载 lua 文件
            // 3)lua 的 每一次require 操作不管是否成功都会触发1的回调
            this.luaEnv.DoString("require 'luaFile001'");
            Debug.Log(this.luaEnv.Global.Get<string>("b")); // 输出 bbbb
            Debug.Log(this.luaEnv.Global.Get<string>("c")); // 输出 null,回调函数里覆盖了lua的内容。c的赋值没了。。
        }

        /// <summary>
        /// 加载Lua脚本的回调
        /// </summary>
        /// <param name="fileName">要加载的Lua脚本名字</param>
        /// <returns>加载到的Lua脚本</returns>
        byte[] loadedLua(ref string fileName)
        {
            if (fileName == "luaFile001")
            {
                string script = "b = 'bbbb'";
                return System.Text.Encoding.UTF8.GetBytes(script);
            }
            return null; 
        }

        // void Update()
        // {
        //     if (luaEnv != null)
        //     {
        //         this.luaEnv.Tick();
        //     }
        // }

        // private void OnDestroy()
        // {
        //     this.luaEnv.Dispose();
        // }
    }
/* LuaCode */
c = 'cccc'