(一)做一个lua管理器,保证解析器的唯一性,封装一些解析器常用函数
单例模式代码:
/// <summary>
/// 单例模式基类
/// </summary>
public class BaseManager<T> where T:new()
{
private static T instance;
public static T GetInstance()
{
if (instance == null)
{
instance = new T();
}
return instance;
}
}
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;
/// <summary>
/// 保证解析器的唯一性,先继承单例模式,也提供些解析器的函数
/// </summary>
public class LuaMgr :BaseManager<LuaMgr>
{
//定义解析器对象
private LuaEnv luaEnv;
//初始化解析器
public void Init()
{
if (luaEnv != null)
return;
luaEnv = new LuaEnv();
//自定义加载器
luaEnv.AddLoader(MyCustomLoader);
}
private byte[] MyCustomLoader(ref string filepath)
{
string path = Application.dataPath + "/Lua/" + filepath + ".lua";
Debug.Log(path);
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader加载器加载lua文件失败");
return null;
}
}
//执行lua文件
public void DoString(string str)
{
if (luaEnv == null)
{
Debug.Log("lua解析器未初始化");
return;
}
luaEnv.DoString(str);
}
//清空垃圾
public void Tick()
{
if (luaEnv == null)
{
Debug.Log("lua解析器未初始化");
return;
}
luaEnv.Tick();
}
//销毁解析器
public void Dispose()
{
if (luaEnv == null)
{
Debug.Log("lua解析器未初始化");
return;
}
luaEnv.Dispose();
luaEnv = null;
}
}
(二)通过ab包加载lua文件
(1)准备好lua文件的ab包
过程:
1.lua文件打成lua包,注意lua文件要改后缀.txt
2.通过assetbundle broswer打包(至少要用2019.3以上版本的unity才有这个)
选择好打包平台:我的是mac,打包压缩格式为lz4
打包结果:
(2)编写自定义ab包加载器,并让luaenv添加这个自定义加载器
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;
/// <summary>
/// 保证解析器的唯一性,先继承单例模式,也提供些解析器的函数
/// </summary>
public class LuaMgr :BaseManager<LuaMgr>
{
//定义解析器对象
private LuaEnv luaEnv;
//初始化解析器
public void Init()
{
if (luaEnv != null)
return;
luaEnv = new LuaEnv();
//添加自定义加载器
luaEnv.AddLoader(MyCustomLoader);
//添加自定义的ab包加载器
luaEnv.AddLoader(MyCustomABLoader);
}
/// <summary>
/// 普通加载器
/// </summary>
/// <param name="filepath">lua文件名</param>
/// <returns></returns>
private byte[] MyCustomLoader(ref string filepath)
{
string path = Application.dataPath + "/Lua/" + filepath + ".lua";
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader加载器加载lua文件失败");
return null;
}
}
/// <summary>
/// 用ab包的方式加载lua文件的加载器
/// </summary>
/// <param name="filepath">lua文件名</param>
/// <returns></returns>
private byte[] MyCustomABLoader(ref string filepath)
{
Debug.Log("用ab包加载lua文件");
//找到ab包的路径
string path = Application.streamingAssetsPath + "/lua";
//加载含有lua文件的ab包
AssetBundle luaab = AssetBundle.LoadFromFile(path);
//加载ab包里的lua文件,读成txt,这里注意,因为打包的时候后缀是.lua.txt所以文件名还要加上个.lua
TextAsset txt = luaab.LoadAsset<TextAsset>(filepath + ".lua");
return txt.bytes;
}
测试代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;//要添加这个命名空间
using System.IO;
public class LuaEnvTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoString("require('Main')");
}
}
测试结果:
这里是因为执行require时,会依次遍历所有自定义加载器,如果都没有,就去默认路径Resources文件夹下找。
ps:只需要最后测试ab包的时候用ab包加载器,平时不需要,只需要用普通加载器
(3)luamgr的一点优化
1.不用每次都写require,增加一个方法
/// <summary>
/// 拼接require不用写那么多次require
/// </summary>
/// <param name="filepath">lua文件名</param>
public void DoLuaFile(string filepath)
{
string str = string.Format("require('{0}')", filepath);
DoString(str);
}
2.得到lua的_G
/// <summary>
/// 声明了一个属性,得到lua中得_G
/// </summary>
public LuaTable Global
{
get
{
return luaEnv.Global;
}
}
整个完整的luaenv管理器的代码:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;
/// <summary>
/// 保证解析器的唯一性,先继承单例模式,也提供些解析器的函数
/// </summary>
public class LuaMgr :BaseManager<LuaMgr>
{
//定义解析器对象
private LuaEnv luaEnv;
/// <summary>
/// 声明了一个属性,得到lua中得_G
/// </summary>
public LuaTable Global
{
get
{
return luaEnv.Global;
}
}
//初始化解析器
public void Init()
{
if (luaEnv != null)
return;
luaEnv = new LuaEnv();
//添加自定义加载器
luaEnv.AddLoader(MyCustomLoader);
//添加自定义的ab包加载器
luaEnv.AddLoader(MyCustomABLoader);
}
/// <summary>
/// 普通加载器
/// </summary>
/// <param name="filepath">lua文件名</param>
/// <returns></returns>
private byte[] MyCustomLoader(ref string filepath)
{
string path = Application.dataPath + "/Lua/" + filepath + ".lua";
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader加载器加载lua文件失败");
return null;
}
}
/// <summary>
/// 用ab包的方式加载lua文件的加载器
/// </summary>
/// <param name="filepath">lua文件名</param>
/// <returns></returns>
private byte[] MyCustomABLoader(ref string filepath)
{
Debug.Log("用ab包加载lua文件");
//找到ab包的路径
string path = Application.streamingAssetsPath + "/lua";
//加载含有lua文件的ab包
AssetBundle luaab = AssetBundle.LoadFromFile(path);
//加载ab包里的lua文件,读成txt,这里注意,因为打包的时候后缀是.lua.txt所以文件名还要加上个.lua
TextAsset txt = luaab.LoadAsset<TextAsset>(filepath + ".lua");
return txt.bytes;
}
//执行lua文件
public void DoString(string str)
{
if (luaEnv == null)
{
Debug.Log("lua解析器未初始化");
return;
}
luaEnv.DoString(str);
}
/// <summary>
/// 拼接require不用写那么多次require
/// </summary>
/// <param name="filepath">lua文件名</param>
public void DoLuaFile(string filepath)
{
string str = string.Format("require('{0}')", filepath);
DoString(str);
}
//清空垃圾
public void Tick()
{
if (luaEnv == null)
{
Debug.Log("lua解析器未初始化");
return;
}
luaEnv.Tick();
}
//销毁解析器
public void Dispose()
{
if (luaEnv == null)
{
Debug.Log("lua解析器未初始化");
return;
}
luaEnv.Dispose();
luaEnv = null;
}
}