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