【Unity】热更新之xLua C#调用Lua / 自定义加载器 / 加载并执行AB包中的Lua文件

最近在学习xLua,和大家分享一下学习笔记。

下载xLua

xLua的GitHub下载地址:xLua下载-GitHub-点击进入
xLua GitHub
点击链接进入后,首先点击Code,再点击Download ZIP把压缩包下载下来,下载完后解压得到xLua-master文件夹,在Assets目录下将Plugins文件夹和XLua文件夹拷贝到你的Unity工程的Assets目录下即可导入XLua。
导入后先清理一下xLua产生的代码,不然可能会报错
在这里插入图片描述

C#执行Lua代码(xLua)

首先需要引入XLua命名空间,使用xLua提供的Lua解析器LuaEnv中的DoString方法即可执行Lua代码。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class LuaTest : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    void Start()
    {
    
    
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString("print('Hello world!')");
    }
}

将脚本挂到场景的任何一个物体下,点击运行即可看到输出。
Hello world
虽然执行成功了,但是直接把全部Lua代码写在DoString的参数里面显然有点傻,也不符合我们日常编码习惯,所以我们需要用到Lua的require(“Lua文件名”)来执行一段lua代码。
接下来修改一下代码,首先创建一个lua文件(可以直接创建一个文本文件,然后修改后缀名为.lua)保存在Resources文件夹中(默认从Resources文件夹加载lua文件),我这里用的Sublime Text打开编辑(可以使用任何IDE,记事本也可以),随便写一句Lua代码。

保存后关闭编辑器,将你刚创建的Lua代码的后缀名改成txt,直接在后面加上.txt(MyLua.lua.txt)。这里改后缀名的原因我估计是Unity Resources加载文件方法不能识别后缀名为.lua的文件,所以后缀名需要改为.txt。(这里只是我的猜想)
修改刚刚的C#代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class LuaTest : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    void Start()
    {
    
    
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString("require('MyLua')");
    }
}

返回Unity,点击运行即可看到Lua脚本的输出。

自定义加载器

上面require(‘Lua文件名’)默认是从Resources上面加载的,如果我们想自定义加载路径怎么办?况且Resources文件夹只是可读的,需要热更新的Lua代码因为需要动态读写,不会存放在Resources里面,那就要需要自定义加载器了。
那如何自定义加载器呢?LuaEnv给我们提供一个方法,我们进入LuaEnv.cs看看。
LuaEnv.cs
这里我们看到有一个AddLoader的方法,参数传入一个委托。我们先定义一个和AddLoader所需要的委托一致的方法MyCustomLoader,这个方法就是我们的自定义加载器,filepath传入的是LuaEnv.DoString(“require(‘Lua文件名’)”)中的Lua文件名。然后添加自定义加载器luaEnv.AddLoader(MyCustomLoader);

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;

public class LuaTest : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    void Start()
    {
    
    
        LuaEnv luaEnv = new LuaEnv();
        //添加自定义加载器
        luaEnv.AddLoader(MyCustomLoader);
        luaEnv.DoString("require('MyLua')");
    }

    byte[] MyCustomLoader(ref string filepath)
    {
    
    
        //根据文件名,自定义加载路径,我这里是Asset文件夹下新建了一个Lua文件夹
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        //这里判断一下文件是否存在	File需要引用System.IO命名空间
        if (File.Exists(path))
        {
    
    
            //如果存在,将文件读取出来并返回出去
            return File.ReadAllBytes(path);
        }
        //如果不存在就返回空
        return null;
    }
}

下面是Lua代码,这里Lua代码因为使用File来读取的文件,所以可以不用修改后缀名为.txt。

--MyLua.lua 代码
print("my lua!")

自定义加载器会比默认加载器先执行,也就是说,xLua会先到自定义加载器中加载Lua文件,当全部自定义加载器(可以有多个自定义加载器)加载失败再到默认加载器中加载Lua文件。
返回Unity运行后可以都看到Lua的输出,说明我们已经正确的加载并执行了Lua文件。
在这里插入图片描述

自定义加载器加载AB包中的Lua文件

因为AB包加载资源不支持lua文件,这里需要先将Lua代码的后缀名添加.txt(我这的文件名是MyLua.lua.txt),然后打包到AB包中,打包时如果出现打包失败并报错,可以尝试清理一下XLua生成的代码,再打AB包。
在这里插入图片描述
我们再自定义一个加载器用来加载AB包中的Lua文件

	byte[] MyABCustomLoader(ref string filepath)
    {
    
    
        //先加载Lua文件所在的AB包
        AssetBundle abPage = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/lua");
        //从AB包中加载对应的Lua文件
        TextAsset luaText = abPage.LoadAsset<TextAsset>(filepath + ".lua");

        if (luaText != null)
            return luaText.bytes;

        return null;
    }

接着AddLoader我们自定义的这个加载器就可以了,完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;

public class LuaTest : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    void Start()
    {
    
    
        LuaEnv luaEnv = new LuaEnv();
        //添加自定义加载器
        luaEnv.AddLoader(MyCustomLoader);
        luaEnv.AddLoader(MyABCustomLoader);

        luaEnv.DoString("require('MyLua')");
    }

    /// <summary>
    /// 自定义加载器,用来加载自定义路径中的Lua文件
    /// </summary>
    /// <param name="filepath">Lua文件名</param>
    /// <returns>Lua文件字节数组</returns>
    byte[] MyCustomLoader(ref string filepath)
    {
    
    
        //根据文件名,自定义加载路径,我这里是Asset文件夹下新建了一个Lua文件夹
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        //这里判断一下文件是否存在	File需要引用System.IO命名空间
        if (File.Exists(path))
        {
    
    
            //如果存在,将文件读取出来并返回出去
            return File.ReadAllBytes(path);
        }
        //如果不存在就返回空
        return null;
    }

    /// <summary>
    /// 自定义加载器,用来加载AB包中的Lua文件
    /// </summary>
    /// <param name="filepath">Lua文件名</param>
    /// <returns>Lua文件字节数组</returns>
    byte[] MyABCustomLoader(ref string filepath)
    {
    
    
        //先加载Lua文件所在的AB包
        AssetBundle abPage = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/lua");
        //从AB包中加载对应的Lua文件
        TextAsset luaText = abPage.LoadAsset<TextAsset>(filepath + ".lua");

        if (luaText != null)
            return luaText.bytes;

        return null;
    }
}

以上就是这篇文章的所有内容了,如有那个地方写的不准确,劳烦大佬指出,感谢,希望对各位看官有所帮助!

猜你喜欢

转载自blog.csdn.net/weixin_43453797/article/details/126709008
今日推荐