1. 默认加载文件路径
StreamingAssets
目录下的.lua文件
注意要引用命名空间
using XLua;
//Lua解析器 能够让我们在Unity中执行Lua
//一般情况下 保持它的唯一性
LuaEnv env = new LuaEnv();
//执行Lua语言
env.DoString("print('你好世界')");
//执行一个Lua脚本 Lua知识点 :多脚本执行 require
//默认寻找脚本的路径 是在 Resources下 并且 因为在这里
//估计是通过 Resources.Load去加载Lua脚本 txt bytes等等
//所以Lua脚本 后缀要加一个txt
env.DoString("require('Main')");
//帮助我们清楚Lua中我们没有手动释放的对象 垃圾回收
//帧更新中定时执行 或者 切场景时执行
env.Tick();
//销毁Lua解析器
env.Dispose();
2. lua 文件加载
xlua 提供的一个路径重定向的方法
允许我们自定义加载lua文件的规则
当我们执行lua语言 require时 相当于执行一个lua脚本
他就会执行 我们自定义的这个函数
void Start()
{
LuaEnv env = new LuaEnv();
//xlua提供的一个 路径重定向 的方法
//允许我们自定义 加载 Lua文件的规则
//当我们执行Lua语言 require 时 相当于执行一个lua脚本
//它就会 执行 我们自定义传入的这个函数
env.AddLoader(MyCustomLoader);
//最终我们其实 会去AB包中加载 lua文件
env.DoString("require('Main')");
}
//自动执行
private byte[] MyCustomLoader(ref string filePath)
{
//通过函数中的逻辑 去加载 Lua文件
//传入的参数 是 require执行的lua脚本文件名
//拼接一个Lua文件所在路径
string path = Application.dataPath + "/Lua/" + filePath + ".lua";
Debug.Log(path);
//有路径 就去加载文件
//File知识点 C#提供的文件读写的类
//判断文件是否存在
if ( File.Exists(path) )
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader重定向失败,文件名为" + filePath);
}
return null;
}
4. 全局变量获取
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//int local = LuaMgr.GetInstance().Global.Get<int>("testLocal");
//Debug.Log("testLocal:" + local);
//使用lua解析器luaenv中的 Global属性
int i = LuaMgr.GetInstance().Global.Get<int>("testNumber");
Debug.Log("testNumber:" + i);
i = 10;
//改值
LuaMgr.GetInstance().Global.Set("testNumber", 55);
//值拷贝 不会影响原来Lua中的值
int i2 = LuaMgr.GetInstance().Global.Get<int>("testNumber");
Debug.Log("testNumber_i2:" + i2);
bool b = LuaMgr.GetInstance().Global.Get<bool>("testBool");
Debug.Log("testBool:" + b);
float f = LuaMgr.GetInstance().Global.Get<float>("testFloat");
Debug.Log("testFloat:" + f);
double d = LuaMgr.GetInstance().Global.Get<double>("testFloat");
Debug.Log("testFloat_double:" + d);
string s = LuaMgr.GetInstance().Global.Get<string>("testString");
Debug.Log("testString:" + s);
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;
/// <summary>
/// Lua管理器
/// 提供 lua解析器
/// 保证解析器的唯一性
/// </summary>
public class LuaMgr : BaseManager<LuaMgr>
{
//执行Lua语言的函数
//释放垃圾
//销毁
//重定向
private LuaEnv luaEnv;
/// <summary>
/// 得到Lua中的_G
/// </summary>
public LuaTable Global
{
get
{
return luaEnv.Global;
}
}
/// <summary>
/// 初始化解析器
/// </summary>
public void Init()
{
//已经初始化了 别初始化 直接返回
if (luaEnv != null)
return;
//初始化
luaEnv = new LuaEnv();
//加载lua脚本 重定向
luaEnv.AddLoader(MyCustomLoader);
luaEnv.AddLoader(MyCustomABLoader);
}
//自动执行
private byte[] MyCustomLoader(ref string filePath)
{
//通过函数中的逻辑 去加载 Lua文件
//传入的参数 是 require执行的lua脚本文件名
//拼接一个Lua文件所在路径
string path = Application.dataPath + "/Lua/" + filePath + ".lua";
//有路径 就去加载文件
//File知识点 C#提供的文件读写的类
//判断文件是否存在
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
Debug.Log("MyCustomLoader重定向失败,文件名为" + filePath);
}
return null;
}
//Lua脚本会放在AB包
//最终我们会通过加载AB包再加载其中的Lua脚本资源 来执行它
//重定向加载AB包中的LUa脚本
private byte[] MyCustomABLoader(ref string filePath)
{
//Debug.Log("进入AB包加载 重定向函数");
从AB包中加载lua文件
加载AB包
//string path = Application.streamingAssetsPath + "/lua";
//AssetBundle ab = AssetBundle.LoadFromFile(path);
加载Lua文件 返回
//TextAsset tx = ab.LoadAsset<TextAsset>(filePath + ".lua");
加载Lua文件 byte数组
//return tx.bytes;
//通过我们的AB包管理器 加载的lua脚本资源
TextAsset lua = ABMgr.GetInstance().LoadRes<TextAsset>("lua", filePath + ".lua");
if (lua != null)
return lua.bytes;
else
Debug.Log("MyCustomABLoader重定向失败,文件名为:" + filePath);
return null;
}
public void DoLuaFile(string fileName)
{
string str = string.Format("require('{0}')", fileName);
DoString(str);
}
public void DoString(string str)
{
if(luaEnv == null)
{
Debug.Log("解析器为初始化");
return;
}
luaEnv.DoString(str);
}
public void Tick()
{
if (luaEnv == null)
{
Debug.Log("解析器为初始化");
return;
}
luaEnv.Tick();
}
public void Dispose()
{
if (luaEnv == null)
{
Debug.Log("解析器为初始化");
return;
}
try
{
luaEnv.Dispose();
luaEnv = null;
Debug.Log("释放成功");
}
catch (System.Exception ex)
{
Debug.Log(ex.Message);
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using XLua;
//无参无返回值的委托
public delegate void CustomCall();
//有参有返回 的委托
//该特性是在XLua命名空间中的
//加了过后 要在编辑器里 生成 Lua代码
[CSharpCallLua]
public delegate int CustomCall2(int a);
[CSharpCallLua]
public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e);
[CSharpCallLua]
public delegate int CustomCall4(int a, ref int b, ref bool c, ref string d, ref int e);
[CSharpCallLua]
public delegate void CustomCall5(string a, params int[] args);//变长参数的类型 是根据实际情况来定的
public class Lesson5_CallFunction : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//无参无返回的获取
//委托
CustomCall call = LuaMgr.GetInstance().Global.Get<CustomCall>("testFun");
call();
//Unity自带委托
UnityAction ua = LuaMgr.GetInstance().Global.Get<UnityAction>("testFun");
ua();
//C#提供的委托
Action ac = LuaMgr.GetInstance().Global.Get<Action>("testFun");
ac();
//Xlua提供的一种 获取函数的方式 少用
LuaFunction lf = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun");
lf.Call();
//有参有返回
CustomCall2 call2 = LuaMgr.GetInstance().Global.Get<CustomCall2>("testFun2");
Debug.Log("有参有返回:" + call2(10));
//C#自带的泛型委托 方便我们使用
Func<int, int> sFun = LuaMgr.GetInstance().Global.Get<Func<int, int>>("testFun2");
Debug.Log("有参有返回:" + sFun(20));
//Xlua提供的
LuaFunction lf2 = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun2");
Debug.Log("有参有返回:" + lf2.Call(30)[0]);
//多返回值
//使用 out 和 ref 来接收
CustomCall3 call3 = LuaMgr.GetInstance().Global.Get<CustomCall3>("testFun3");
int b;
bool c;
string d;
int e;
Debug.Log("第一个返回值:" + call3(100, out b, out c, out d, out e));
Debug.Log(b + "_" + c + "_" + d + "_" + e);
CustomCall4 call4 = LuaMgr.GetInstance().Global.Get<CustomCall4>("testFun3");
int b1 = 0;
bool c1 = true;
string d1 = "";
int e1 = 0;
Debug.Log("第一个返回值:" + call4(200, ref b1, ref c1, ref d1, ref e1));
Debug.Log(b1 + "_" + c1 + "_" + d1 + "_" + e1);
//Xlua
LuaFunction lf3 = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun3");
object[] objs = lf3.Call(1000);
for( int i = 0; i < objs.Length; ++i )
{
Debug.Log("第" + i + "个返回值是:" + objs[i]);
}
//变长参数
CustomCall5 call5 = LuaMgr.GetInstance().Global.Get<CustomCall5>("testFun4");
call5("123", 1, 2, 3, 4, 5, 566, 7, 7, 8, 9, 99);
LuaFunction lf4 = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun4");
lf4.Call("456", 6, 7, 8, 99, 1);
}
// Update is called once per frame
void Update()
{
}
}
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//同一类型List
List<int> list = LuaMgr.GetInstance().Global.Get<List<int>>("testList");
Debug.Log("*******************List************************");
for ( int i = 0; i <list.Count; ++i )
{
Debug.Log(list[i]);
}
//值拷贝 浅拷贝 不会改变lua中的内容
list[0] = 100;
List<int> list2 = LuaMgr.GetInstance().Global.Get<List<int>>("testList");
Debug.Log(list2[0]);
//不指定类型 object
List<object> list3 = LuaMgr.GetInstance().Global.Get<List<object>>("testList2");
Debug.Log("*******************List object************************");
for (int i = 0; i < list3.Count; ++i)
{
Debug.Log(list3[i]);
}
Debug.Log("*******************Dictionary************************");
Dictionary<string, int> dic = LuaMgr.GetInstance().Global.Get<Dictionary<string, int>>("testDic");
foreach (string item in dic.Keys)
{
Debug.Log(item + "_" + dic[item]);
}
dic["1"] = 100000;
//值拷贝 不会改变lua中的内容
Dictionary<string, int> dic2 = LuaMgr.GetInstance().Global.Get<Dictionary<string, int>>("testDic");
Debug.Log(dic2["1"]);
Debug.Log("*******************Dictionary object************************");
Dictionary<object, object> dic3 = LuaMgr.GetInstance().Global.Get<Dictionary<object, object>>("testDic2");
foreach (object item in dic3.Keys)
{
Debug.Log(item + "_" + dic3[item]);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using XLua;
public class CallLuaClass
{
//在这个类中去声明成员变量
//名字一定要和 Lua那边的一样
//公共 私有和保护 没办法赋值
//这个自定义中的 变量 可以更多也可以更少
//如果变量比 lua中的少 就会忽略它
//如果变量比 lua中的多 不会赋值 也会忽略
public int testInt;
public bool testBool;
//public float testFloat;
public float testString;
public UnityAction testFun;
public CallLuaInClass testInClass;
public int i;
public void Test()
{
Debug.Log(testInt);
}
}
public class CallLuaInClass
{
public int testInInt;
}
public class CallLuaInClassDic
{
public Dictionary<string, int> testDic;
}
public class Lesson7_CallClass : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
CallLuaClass obj = LuaMgr.GetInstance().Global.Get<CallLuaClass>("testClas");
Debug.Log(obj.testInt);
Debug.Log(obj.testBool);
//Debug.Log(obj.testFloat);
Debug.Log(obj.testString);
Debug.Log(obj.i);
//Debug.Log("嵌套:" + obj.testInClass.testInInt);
obj.testFun();
//值拷贝 改变了它 不会改变Lua表里的内容
obj.testInt = 100;
CallLuaClass obj2 = LuaMgr.GetInstance().Global.Get<CallLuaClass>("testClas");
Debug.Log(obj2.testInt);
CallLuaInClassDic obj3 = LuaMgr.GetInstance().Global.Get<CallLuaInClassDic>("testClass");
Debug.Log(obj3.testDic);
Debug.Log(obj3.testDic.Count);
foreach(string item in obj3.testDic.Keys)
{
Debug.Log(obj3.testDic[item]);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using XLua;
//接口中是不允许有成员变量的
//我们用属性来接受
//接口和类规则一样 其中的属性多了少了 不影响结果 无非就是忽略他们
//嵌套几乎和类一样 无非 是要遵循接口的规则
[CSharpCallLua]
public interface ICSharpCallInterface
{
int testInt
{
get;
set;
}
bool testBool
{
get;
set;
}
float testFloat
{
get;
set;
}
string testString
{
get;
set;
}
UnityAction testFun
{
get;
set;
}
float testFloat222
{
get;
set;
}
}
public class Lesson8_CallInterface : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
ICSharpCallInterface obj = LuaMgr.GetInstance().Global.Get<ICSharpCallInterface>("testClas");
Debug.Log(obj.testInt);
Debug.Log(obj.testBool);
Debug.Log("新加的:" + obj.testFloat222);
Debug.Log(obj.testString);
obj.testFun();
//接口拷贝 是引用拷贝 改了值 lua表中的值也变了
obj.testInt = 10000;
ICSharpCallInterface obj2 = LuaMgr.GetInstance().Global.Get<ICSharpCallInterface>("testClas");
Debug.Log(obj2.testInt);
}
// Update is called once per frame
void Update()
{
}
}
不建议使用LuaTable和LuaFunction 效率低
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class Lesson9_CallLuaTable : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
//不建议使用LuaTable和LuaFunction 效率低
//引用对象
LuaTable table = LuaMgr.GetInstance().Global.Get<LuaTable>("testClas");
Debug.Log(table.Get<int>("testInt"));
Debug.Log(table.Get<bool>("testBool"));
Debug.Log(table.Get<float>("testFloat"));
Debug.Log(table.Get<string>("testString"));
table.Get<LuaFunction>("testFun").Call();
//改 引用
table.Set("testInt", 55);
Debug.Log(table.Get<int>("testInt"));
LuaTable table2 = LuaMgr.GetInstance().Global.Get<LuaTable>("testClas");
Debug.Log(table2.Get<int>("testInt"));
table.Dispose();
table2.Dispose();
}
// Update is called once per frame
void Update()
{
}
}