xlua解析器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class Example : MonoBehaviour
{
void Start()
{
//获得xlua的解析器
LuaEnv env = new LuaEnv();
//解析器运行Lua代码
env.DoString("print('hello world');");
//解析器释放
env.Dispose();
}
}
调用方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class DoString : MonoBehaviour
{
void Start()
{
//luaCallCSharpCode();
luaReturnData();
}
//lua中调用C#方法
public void luaCallCSharpCode()
{
LuaEnv env = new LuaEnv();
//lua中调用C# CS.命名空间.类名.方法名(参数)
env.DoString("CS.UnityEngine.Debug.Log('you good')");
env.Dispose();
}
//lua返回值给C#
public void luaReturnData()
{
LuaEnv env = new LuaEnv();
var con = env.DoString("return 100,true");
Debug.Log(con[0]);
Debug.Log(con[1]);
env.Dispose();
}
}
加载lua脚本
默认加载器
要将lua脚本放在StreamingAssets文件夹下(自己创建的)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class Loader : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
//对应test.lua
//内置加载器会扫描预制的目录,查找是否存在test.lua
//xlua存在默认加载器,可在StreamingAssets文件夹中加载脚本
env.DoString("require('test')");
env.Dispose();
}
}
AddLoader方法
- 需要的是委托
自定义加载器
- 自定义加载器会优先于内置的加载器
- 当Lua代码执行require()函数时,自定义加载器会尝试获得文件的内容
- 参数:被加载Lua文件的路径
- xLua的解析环境,会执行我们自定义加载器返回的Lua代码
using UnityEngine;
using System.IO;
using XLua;
public class Loader : MonoBehaviour
{
void Start()
{
LuaEnv env = new LuaEnv();
//将自定义的加载器,加入到xlua的解析器环境中
env.AddLoader(Envpath);
env.DoString("require('test1')");
env.Dispose();
}
private byte[] Envpath(ref string filepath)
{
//指向Assets路径
string path = Application.dataPath;
//该路径减掉7个字符(减掉Assets,包括一个/),加上自定义的路径,文件名,文件后缀名
path = path.Substring(0, path.Length - 7) + "/DataPath/Lua/" + filepath + ".lua";
//如果文件存在
if (File.Exists(path))
{
//返回的是字节数组
return File.ReadAllBytes(path);
}
else
{
return null;
}
}
}
自定义编辑器
- 单例模式
- 创建编辑器的构造函数
- 自定义加载器,AddLoader在构造函数中执行
- 执行lua脚本的方法DoString
- 销毁编辑器
using UnityEngine;
using System.IO;
using XLua;
public class xluaEnv
{
#region 单例模式
private static xluaEnv instance;
public static xluaEnv Instance
{
get
{
if (instance == null)
{
instance = new xluaEnv();
}
return instance;
}
}
#endregion
#region 创建编辑器的构造函数
private LuaEnv _Env;
private xluaEnv()
{
_Env = new LuaEnv();
_Env.AddLoader(Envpath);
}
#endregion
#region 自定义加载器
private byte[] Envpath(ref string filepath)
{
string path = Application.dataPath;
path = path.Substring(0, path.Length - 7) + "/DataPath/Lua/" + filepath + ".lua";
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
return null;
}
}
#endregion
#region 执行lua脚本
private object[] DoString(string code)
{
return _Env.DoString(code);
}
#endregion
#region 销毁
public void Free()
{
_Env.Dispose();
instance = null;
}
#endregion
}
lua调用C#
静态方法
C#代码
using UnityEngine;
namespace AJ
{
public static class LuaCallStatic
{
public static int ID = 99;
public static string Name
{
get;
set;
}
public static string OutPut()
{
return "output返回";
}
public static void Default(string rb = "abs")
{
Debug.Log(rb);
}
}
}
lua代码
- 规则:CS.命名空间.类名.变量名
--lua调用C#静态类
--规则CS.命名空间.类名.变量名
print(CS.AJ.LuaCallStatic.ID)
local x = CS.AJ.LuaCallStatic.Name
x = "admin"
print(x)
print(CS.AJ.LuaCallStatic.OutPut())
CS.AJ.LuaCallStatic.Default()
CS.AJ.LuaCallStatic.Default("canChange")
类对象
C#代码
public class LuaCallObject
{
private string Name;
public int HP
{
get;
set;
}
public LuaCallObject()
{
}
public LuaCallObject(string name)
{
this.Name = name;
}
public string OutPut()
{
return Name;
}
}
lua代码
- 规则CS.构造函数
- 调用对象内的函数用 :
- Lua实例化GameObject
--lua调用C#对象
--规则CS.构造函数
local object = CS.LuaCallObject()
--未赋值,nil
print(object.Name)
object.HP = 100
print(object.HP)
local object1 = CS.LuaCallObject("Tom")
--调用对象内的函数、
--用 :
print(object1:OutPut())
--Lua实例化GameObject
--参数为变量名
CS.UnityEngine.GameObject("LuaCreateGO")
结构体
C#代码
using UnityEngine;
public struct TestStruct
{
public string Name;
public string OutPut()
{
return Name;
}
}
public class LuaCallStruct : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallStruct')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
Lua代码
- 和对象调用一致
规则CS.结构体
这里不是构造方法
--lua调用C#结构体
--和对象调用一致
--规则CS.结构体
--这里不是构造方法
local object = CS.TestStruct()
print(object.Name)
print(object:OutPut())
枚举
C#代码
using UnityEngine;
public enum type
{
Tom,
Jerry,
Dog
}
public class LuaCallenum : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallenum')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
lua代码
- 规则:CS.命名空间.枚举名.枚举值
- 枚举获得是userdata自定义数据类型
- 转换获得枚举值 __CastFroom(参数)方法,参数可以是数值或字符串
--调用枚举
--CS.命名空间.枚举名.枚举值
local enum = CS.type.Tom
--枚举获得是userdata自定义数据类型
print(type(enum))
print(enum)
print(CS.type.Jerry)
--转换获得枚举值
print(CS.type.__CastFrom(0))
print(CS.type.__CastFrom("Dog"))
继承
C#代码
using UnityEngine;
public class Father
{
public string name;
public void Talk()
{
Debug.Log("父类的方法Talk");
}
public virtual void OverFunc()
{
Debug.Log("父类的虚方法");
}
}
public class Child : Father
{
public override void OverFunc()
{
Debug.Log("子类重写方法");
}
}
public class LuaCallBase : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallBase')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
lua代码
--继承
--调用father
local father = CS.Father()
print(father.name)
father:Talk()
father:OverFunc()
local child = CS.Child()
child:OverFunc()
类的扩展
C#代码
- 类扩展,需要给扩展方法编写的静态类添加[LuaCallCSharp],否则lua无法调用
using UnityEngine;
using XLua;
public class TestShow
{
public void show()
{
Debug.Log("输出方法show");
}
}
//类扩展,需要给扩展方法编写的静态类添加[LuaCallCSharp],否则lua无法调用
[LuaCallCSharp]
public static class IsExtend
{
public static void ExtendFunc(this TestShow testShow)
{
Debug.Log("扩展类方法ExtendFunc");
}
}
public class LuaCallExtend : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallExtend')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
lua代码:
--类的扩展
local testShow = CS.TestShow()
testShow:show()
testShow:ExtendFunc()
遇到问题:添加了 [LuaCallCSharp] 后,依然无法在lua中调用扩展的方法
解决方法:先 Clear Generate Code ,再 Generate Code 一遍
委托
C#代码
using UnityEngine;
public delegate void DeleShow();
public class IsDelegate
{
public static DeleShow DeleStatic;
public DeleShow Dymatic;
public static void Show()
{
Debug.Log("委托方法输出");
}
}
public class LuaCallDelegate : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallDelegate')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
Lua代码
静态委托
- 委托赋值不需要加括号
- Lua中添加了函数到静态委托变量后,如果不再使用委托,要释放添加的委托
--委托
--注意委托赋值不需要加括号
CS.IsDelegate.DeleStatic = CS.IsDelegate.Show
CS.IsDelegate.DeleStatic()
--Lua中添加了函数到静态委托变量后,如果不再使用委托,要释放添加的委托
CS.IsDelegate.DeleStatic = nil
- 添加lua中定义的方法
- 可以添加多个方法
local func = function()
print("Lua func show")
end
--覆盖添加委托
CS.IsDelegate.DeleStatic = func
CS.IsDelegate.DeleStatic = CS.IsDelegate.DeleStatic + CS.IsDelegate.Show
--这里输出func和Show两个方法的内容
CS.IsDelegate.DeleStatic()
CS.IsDelegate.DeleStatic = CS.IsDelegate.DeleStatic - func
--这里输出Show方法的内容
CS.IsDelegate.DeleStatic()
CS.IsDelegate.DeleStatic = nil
输出结果:
调用方法前判定
--调用前判定,防止为空时调用报错
if(CS.IsDelegate.DeleStatic ~= nil)
then
CS.IsDelegate.DeleStatic()
end
根据委托判定赋值方法
if(CS.IsDelegate.DeleStatic == nil)
then
CS.IsDelegate.DeleStatic = func
else
CS.IsDelegate.DeleStatic = CS.IsDelegate.DeleStatic + func
end
动态委托
local obj = CS.IsDelegate()
obj.Dymatic = func
obj.Dymatic()
obj.Dymatic = nil
事件
C#代码
- 定义事件
- 定义响应事件的方法
using UnityEngine;
public delegate Event EventLua();
public class TestEvent
{
public static event EventLua eventStatic;
public static void StaticFunc()
{
Debug.Log("静态事件的方法输出");
}
//响应eventStatic事件
public static void CallEventStatic()
{
eventStatic?.Invoke();
}
public event EventLua eventDynamic;
public void DynamicFunc()
{
Debug.Log("动态事件方法输出");
}
//响应eventDynamic事件
public void CallEventDynamic()
{
eventDynamic?.Invoke();
}
}
public class LuaCallEvent : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallEvent')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
lua代码
- 静态事件——规则:CS.类名.事件名("+",方法)
- 动态事件——规则:CS.构造函数:事件名("-",方法)
--事件
CS.TestEvent.eventStatic("+",CS.TestEvent.StaticFunc)
CS.TestEvent.CallEventStatic()
CS.TestEvent.eventStatic("-",CS.TestEvent.StaticFunc)
local func = function()
print("Lua func show")
end
local obj = CS.TestEvent()
obj:eventDynamic("+",func)
obj:CallEventDynamic()
obj:eventDynamic("-",func)
泛型
- lua不支持泛型
- 所以只能,在C#中将所有的泛型实现
C#代码
using UnityEngine;
public class TestGeneric
{
public void OutPut<T>(T data)
{
Debug.Log("泛型方法:" + data.ToString());
}
public void OutPut(string data)
{
OutPut<string>(data);
}
public void OutPut(float data)
{
OutPut<float>(data);
}
}
public class LuaCallGenericType : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallGenericType')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
Lua代码
--解决泛型问题
CS.TestGeneric():OutPut("admin")
CS.TestGeneric():OutPut(12)
实现创建物体,同时添加BoxCollider组件
- xlua实现了typeof关键字,所以可以用类型API代替unity内置的泛型方法
local go = CS.UnityEngine.GameObject("CreateObject")
go:AddComponent(typeof(CS.UnityEngine.BoxCollider))
Out 和 Ref
C#代码
using UnityEngine;
public class TestOutRef
{
public string testOut(string data)
{
return data;
}
public string testOut1(string data, out string test)
{
test = "testOut1 out";
return data;
}
public string testRef1(string data, ref string test)
{
test = "testOut2 ref";
return data;
}
public string testOut2(out string data, string test)
{
data = "testOut2 out";
return test;
}
}
public class LuaCallOutRef : MonoBehaviour
{
void Start()
{
xluaEnv.Instance.DoString("require('LcallC/LuaCallOutRef')");
}
void OnDestroy()
{
xluaEnv.Instance.Free();
}
}
lua代码
- 在lua中,不需要out,ref 参数,只需要一个变量来接收out的值
--out ref
local obj = CS.TestOutRef()
print(obj:testOut("tom"))
local out1
local x,y = obj:testOut1("admin",out1)
print(x,y,out1)
local r1,ref2 = obj:testRef1("jerry")
print(r1,ref2)
local o2,out2 = obj:testOut2("dog")
print(o2,out2)
结果: