4.加载自定义路径下的Lua脚本

  1. 4.CSharp调用Lua-Lua文件加载重定向
    1. 4.1 知识点
      1. 准备工作
      2. 自定义路径
      3. 自定义解析方式
        1. 创建一个自定义的 Lua 文件加载器类,继承自 LuaFileUtils,重写读取文件方法。并且要在实例化Lua解析器前实例化Lua 文件加载器类
        2. 游戏打包后lua文件要不从AB包加载,要不就从Resources下加载。自己自定义路径会失效。
        3. MyCustomLoader中读取文件方法ReadFile首先初始化一个字节数组,并返回。因为要从AB包或者Resources下加载,所以文件名要以.lua结尾,没有就添加上去。
        4. toLua提供了拷贝Lua文件到Resources的菜单,但是只会拷贝Lua文件夹下的所有lua脚本,并且在Resources下也保留相对结构,比如也包裹了一层LuaSon文件夹,同时lua脚本都添加了.bytes后缀。因为从Resources加载不能直接加载.lua后缀的文件。
        5. MyCustomLoader的ReadFile方法中添加从Resources加载lua脚本的逻辑
        6. 启动Lua脚本,所有lua脚本会去自定义解析器中从Resources加载了。
        7. 复制一份Lua文件夹和lua脚本,用作打AB包的测试。lua脚本改成.txt后缀。打AB包前要清除toLua生成的代码,否则可能报错。打完在重新生成toLua代码。生成的报错可能因为版本不兼容,注释即可。
        8. MyCustomLoader的ReadFile方法中添加从从AB包加载lua脚本的逻辑
        9. 启动Lua脚本,所有lua脚本会去自定义解析器中从AB包加载了。
        10. 通常我们写的上层Lua代码是放在AB包里的,所以优先从AB包加载
    2. 4.2 知识点代码
      1. Lesson04_CSharp调用Lua_Lua文件加载重定向.lua
      2. LuaSon.lua
      3. MyLua.lua
      4. MyCustomLoader
      5. Lesson04_CSharp调用Lua_Lua文件加载重定向

4.CSharp调用Lua-Lua文件加载重定向


4.1 知识点

准备工作

  • 先实例化虚拟机 并在最后销毁 中间写自定义路径或解析方式相关逻辑
//初始化一个 解析器(虚拟机)
LuaState luaState = new LuaState();

//启动解析器(虚拟机)
luaState.Start();




//检查解析器 栈顶是否为空
luaState.CheckTop();
//销毁解析器
luaState.Dispose();
luaState = null;

自定义路径

  • 自定义解析路径的目的是想要执行不在Lua文件夹下的lua脚本
  • 拼接Lua文件夹下的路径使用Require方法或者DoFile方法,一定要是Lua文件夹的子目录
  • 比如在Lua文件夹下创建一个Luason文件夹和lua脚本
luaState.Require("Lesson04_CSharp调用Lua_Lua文件加载重定向");//我是Lua脚本  Lesson04_CSharp调用Lua_Lua文件加载重定向
luaState.Require("LuaSon/LuaSon");//我是Lua脚本 LuaSon
luaState.DoFile("LuaSon/LuaSon.lua");//我是Lua脚本 LuaSon 
  • 添加Lua文件的搜索路径可以执行不在Lua文件夹下的脚本,在Asset下添加Mylua文件夹和Mylua脚本
//AddSearchPath方法 添加Lua文件的搜索路径 就会去对应路径搜索
//该方法只能指定文件路径 没办法自由的通过AB包来加载文件
luaState.AddSearchPath(Application.dataPath + "/MyLua");//拼接完全路径 也可以不在Lua文件夹下
////RemoveSeachPath方法 移除Lua文件的搜索路径
//luaState.RemoveSeachPath(Application.dataPath + "/MyLua");//假如执行了这句下面的Lua脚本启动就会报错 因为搜索路径被移除了
luaState.Require("MyLua");//我是Lua脚本 MyLua 假如在自定义解析方式下会报错 因为自定义解析方式会去AB包或者Resources下找 无论AB包还是Resources下都没有MyLua脚本

自定义解析方式

创建一个自定义的 Lua 文件加载器类,继承自 LuaFileUtils,重写读取文件方法。并且要在实例化Lua解析器前实例化Lua 文件加载器类

// 创建一个自定义的 Lua 文件加载器类,继承自 LuaFileUtils
public class MyCustomLoader : LuaFileUtils
{
    // 重写 LuaFileUtils 类中的 ReadFile 方法
    public override byte[] ReadFile(string fileName)
    {
        // 重写读取文件方法的具体实现
    }
}
  • 要在实例化Lua解析器前实例化Lua 文件加载器类
#region 知识点二 自定义解析方式

// 初始化自定义文件解析器,因为它的父类是一个单例
// 实例化了它,父类的单例静态变量就会变成该对象
new MyCustomLoader();

#endregion

// 初始化一个解析器(虚拟机)
LuaState luaState = new LuaState();

// 启动解析器(虚拟机)
luaState.Start();

游戏打包后lua文件要不从AB包加载,要不就从Resources下加载。自己自定义路径会失效。

MyCustomLoader中读取文件方法ReadFile首先初始化一个字节数组,并返回。因为要从AB包或者Resources下加载,所以文件名要以.lua结尾,没有就添加上去。

// 创建一个自定义的 Lua 文件加载器类,继承自 LuaFileUtils
public class MyCustomLoader : LuaFileUtils
{
    // 重写 LuaFileUtils 类中的 ReadFile 方法
    public override byte[] ReadFile(string fileName)
    {
        Debug.Log("MyCustomLoader自定义解析方式 文件名:" + fileName);

        // 初始化一个字节数组用于存储文件内容
        byte[] buffer = null;

        // 检查传递进来的 fileName 是否以 ".lua" 后缀结尾,如果没有,则添加 ".lua" 后缀
        if (!fileName.EndsWith(".lua"))
        {
            fileName += ".lua";
        }


        // 从 AssetBundle 包中加载 Lua 脚本

        //从 Resources 文件夹中加载 Lua 脚本

        // 返回存储 Lua 脚本字节数组的 buffer
        return buffer;
    }
}

toLua提供了拷贝Lua文件到Resources的菜单,但是只会拷贝Lua文件夹下的所有lua脚本,并且在Resources下也保留相对结构,比如也包裹了一层LuaSon文件夹,同时lua脚本都添加了.bytes后缀。因为从Resources加载不能直接加载.lua后缀的文件。


MyCustomLoader的ReadFile方法中添加从Resources加载lua脚本的逻辑

//从 Resources 文件夹中加载 Lua 脚本

// 如果在 AssetBundle 包中找不到 Lua 脚本,则尝试从 Resources 文件夹中加载
// 构建路径,通常用于加载 tolua 自带的 Lua 脚本
if (buffer == null)
{
    string path = "Lua/" + fileName;
    // 从 Resources 文件夹中加载名为 path 的 TextAsset 资源
    TextAsset text = Resources.Load(path, typeof(TextAsset)) as TextAsset;

    // 如果成功加载到资源,将其字节数组存储到 buffer 中,并释放 TextAsset 资源
    if (text != null)
    {
        Debug.Log("MyCustomLoader自定义解析方式 从 Resources 文件夹中加载 Lua 脚本");
        buffer = text.bytes;
        Resources.UnloadAsset(text);
    }
}

启动Lua脚本,所有lua脚本会去自定义解析器中从Resources加载了。

#region 知识点二 自定义解析方式

// 初始化自定义文件解析器,因为它的父类是一个单例
// 实例化了它,父类的单例静态变量就会变成该对象
new MyCustomLoader();

#endregion

// 初始化一个解析器(虚拟机)
LuaState luaState = new LuaState();

// 启动解析器(虚拟机)
luaState.Start();

#region 知识点二 自定义解析方式

luaState.Require("Lesson04_CSharp调用Lua_Lua文件加载重定向");//我是Lua脚本  Lesson04_CSharp调用Lua_Lua文件加载重定向
luaState.Require("LuaSon/LuaSon");//我是Lua脚本 LuaSon

#endregion

复制一份Lua文件夹和lua脚本,用作打AB包的测试。lua脚本改成.txt后缀。打AB包前要清除toLua生成的代码,否则可能报错。打完在重新生成toLua代码。生成的报错可能因为版本不兼容,注释即可。









MyCustomLoader的ReadFile方法中添加从从AB包加载lua脚本的逻辑

// 从 AssetBundle 包中加载 Lua 脚本

// 将文件名按 '/' 字符拆分成字符串数组 因为AB包加载文件只需要文件名不需要整个路径 目的是进行分割 得到字符数组最后的元素 就是文件名
string[] strs = fileName.Split('/');

// 使用 AssetBundleManager从 "luascripts" 包中加载名为 fileName 的 TextAsset     strs[strs.Length - 1]得到字符数组最后的元素 就是文件名
TextAsset luaCode = AssetBundleManager.Instance.LoadAssetBundleResource<TextAsset>("luascripts", strs[strs.Length - 1]);

// 如果成功加载到 Lua 脚本,将其字节数组存储到 buffer 中,并释放 TextAsset 资源
if (luaCode != null)
{
    Debug.Log("MyCustomLoader自定义解析方式 从 AssetBundle 包中加载 Lua 脚本");
    buffer = luaCode.bytes;
    Resources.UnloadAsset(luaCode);
}

启动Lua脚本,所有lua脚本会去自定义解析器中从AB包加载了。

#region 知识点二 自定义解析方式

// 初始化自定义文件解析器,因为它的父类是一个单例
// 实例化了它,父类的单例静态变量就会变成该对象
new MyCustomLoader();

#endregion

// 初始化一个解析器(虚拟机)
LuaState luaState = new LuaState();

// 启动解析器(虚拟机)
luaState.Start();

#region 知识点二 自定义解析方式

luaState.Require("Lesson04_CSharp调用Lua_Lua文件加载重定向");//我是Lua脚本  Lesson04_CSharp调用Lua_Lua文件加载重定向
luaState.Require("LuaSon/LuaSon");//我是Lua脚本 LuaSon

#endregion

通常我们写的上层Lua代码是放在AB包里的,所以优先从AB包加载


4.2 知识点代码

Lesson04_CSharp调用Lua_Lua文件加载重定向.lua

print('我是Lua脚本  Lesson04_CSharp调用Lua_Lua文件加载重定向')

LuaSon.lua

print('我是Lua脚本 LuaSon')

MyLua.lua

print('我是Lua脚本 MyLua')

MyCustomLoader

using LuaInterface;
using UnityEngine;

// 创建一个自定义的 Lua 文件加载器类,继承自 LuaFileUtils
public class MyCustomLoader : LuaFileUtils
{
    // 重写 LuaFileUtils 类中的 ReadFile 方法
    public override byte[] ReadFile(string fileName)
    {
        Debug.Log("MyCustomLoader自定义解析方式 文件名:" + fileName);

        // 初始化一个字节数组用于存储文件内容
        byte[] buffer = null;

        // 检查传递进来的 fileName 是否以 ".lua" 后缀结尾,如果没有,则添加 ".lua" 后缀
        if (!fileName.EndsWith(".lua"))
        {
            fileName += ".lua";
        }


        // 从 AssetBundle 包中加载 Lua 脚本

        // 将文件名按 '/' 字符拆分成字符串数组 因为AB包加载文件只需要文件名不需要整个路径 目的是进行分割 得到字符数组最后的元素 就是文件名
        string[] strs = fileName.Split('/');

        // 使用 AssetBundleManager从 "luascripts" 包中加载名为 fileName 的 TextAsset     strs[strs.Length - 1]得到字符数组最后的元素 就是文件名
        TextAsset luaCode = AssetBundleManager.Instance.LoadAssetBundleResource<TextAsset>("luascripts", strs[strs.Length - 1]);

        // 如果成功加载到 Lua 脚本,将其字节数组存储到 buffer 中,并释放 TextAsset 资源
        if (luaCode != null)
        {
            Debug.Log("MyCustomLoader自定义解析方式 从 AssetBundle 包中加载 Lua 脚本");
            buffer = luaCode.bytes;
            Resources.UnloadAsset(luaCode);
        }


        //从 Resources 文件夹中加载 Lua 脚本

        // 如果在 AssetBundle 包中找不到 Lua 脚本,则尝试从 Resources 文件夹中加载
        // 构建路径,通常用于加载 tolua 自带的 Lua 脚本
        if (buffer == null)
        {
            string path = "Lua/" + fileName;
            // 从 Resources 文件夹中加载名为 path 的 TextAsset 资源
            TextAsset text = Resources.Load(path, typeof(TextAsset)) as TextAsset;

            // 如果成功加载到资源,将其字节数组存储到 buffer 中,并释放 TextAsset 资源
            if (text != null)
            {
                Debug.Log("MyCustomLoader自定义解析方式 从 Resources 文件夹中加载 Lua 脚本");
                buffer = text.bytes;
                Resources.UnloadAsset(text);
            }
        }

        // 返回存储 Lua 脚本字节数组的 buffer
        return buffer;
    }
}

Lesson04_CSharp调用Lua_Lua文件加载重定向

using LuaInterface;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson04_CSharp调用Lua_Lua文件加载重定向 : MonoBehaviour
{
    void Start()
    {
        #region 知识点二 自定义解析方式
        
        //初始化自定义文件解析器 因为它的父类是一个单例
        //实例化了它 父类的单例静态变量就会变成该对象
        new MyCustomLoader();
        
        #endregion


        //初始化一个 解析器(虚拟机)
        LuaState luaState = new LuaState();

        //启动解析器(虚拟机)
        luaState.Start();

        #region 知识点二 自定义解析方式
        
        luaState.Require("Lesson04_CSharp调用Lua_Lua文件加载重定向");//我是Lua脚本  Lesson04_CSharp调用Lua_Lua文件加载重定向
        luaState.Require("LuaSon/LuaSon");//我是Lua脚本 LuaSon
        
        #endregion

        #region 知识点一 自定义解析路径

        // //自定义解析路径的目的是 想要 执行不在Lua文件夹下的lua脚本
        //
        //
        // //拼接Lua文件夹下的路径 使用Require方法或者DoFile方法
        // //一定要是Lua文件夹的子目录
        // luaState.Require("Lesson04_CSharp调用Lua_Lua文件加载重定向");//我是Lua脚本  Lesson04_CSharp调用Lua_Lua文件加载重定向
        // luaState.Require("LuaSon/LuaSon");//我是Lua脚本 LuaSon
        // luaState.DoFile("LuaSon/LuaSon.lua");//我是Lua脚本 LuaSon 
        //
        //
        // //添加Lua文件的搜索路径 可以执行不在Lua文件夹下的脚本
        // //AddSearchPath方法 添加Lua文件的搜索路径 就会去对应路径搜索
        // //该方法只能指定文件路径 没办法自由的通过AB包来加载文件
        // luaState.AddSearchPath(Application.dataPath + "/MyLua");//拼接完全路径 也可以不在Lua文件夹下
        // ////RemoveSeachPath方法 移除Lua文件的搜索路径
        // //luaState.RemoveSeachPath(Application.dataPath + "/MyLua");//假如执行了这句下面的Lua脚本启动就会报错 因为搜索路径被移除了
        // luaState.Require("MyLua");//我是Lua脚本 MyLua 假如在自定义解析方式下会报错 因为无论AB包还是Resources下都没有MyLua脚本

        #endregion


        //检查解析器 栈顶是否为空
        luaState.CheckTop();
        //销毁解析器
        luaState.Dispose();
        luaState = null;
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏