安装方法
从github打开腾讯的xlua页面下载xlua包解压复制到Assets文件夹下即可
自定义单例加载器
namespace Code.Rookie
{
//https://shenjun-coder.github.io/LuaBook/大佬的博客
public class XLuaEnv
{
public static XLuaEnv Instance = new XLuaEnv();
private LuaEnv _luaEnv;
private XLuaEnv()
{
_luaEnv = new LuaEnv();
_luaEnv.AddLoader(ProjectLoader);
}
/*
* 自定义加载器,会优先于系统内置加载器执行,当自定义加载器加载到文件以后,后续的加载器则不会执行
* 当Lua代码执行require()函数时,自定义加载器会尝试获得文件的内容
* filepath:被加载Lua文件的路径
* 如果需要加载的文件不存在,返回null
*/
private byte[] ProjectLoader(ref string filepath)
{
//因为 Application.dataPath在上线的代码中无法获得,所以上线时,需要将lua的存储路径,指向到Application.persistentDataPath
string path = Application.dataPath;
string delPath = "Assets";
path = path.Substring(0, path.Length - delPath.Length) + "DataPath/Lua/" + filepath + ".lua";
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
else
{
return null;
}
}
/*
* 释放luaEva
*/
public void Dispose()
{
_luaEnv.Dispose();
Instance = null;
}
public object[] DoString(string code)
{
return _luaEnv.DoString(code);
}
public LuaTable Global
{
get { return _luaEnv.Global; }
}
}
}
lua调用C#
lua调用静态类
c#脚本
namespace Code.C2L
{
public class LuaCallStatic : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallStatic')");//lua脚本位置
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public static class TestStatic
{
public static int ID = 99;
public static string Name { get; set; }
public static string Output()
{
return "static";
}
public static void Default(string str = "abc")
{
Debug.Log(str);
}
}
}
lua脚本
--lua调用静态类
--调用规则(CS.命名空间.类名.变量/函数)
print(CS.Code.C2L.TestStatic.ID)
CS.Code.C2L.TestStatic.Name = "luanb"
print(CS.Code.C2L.TestStatic.Name)
print(CS.Code.C2L.TestStatic.Output())
--使用默认值
CS.Code.C2L.TestStatic.Default()
--使用lua传递的值
CS.Code.C2L.TestStatic.Default("def")
输出结果
lua调用对象
c#代码
namespace Code.C2L
{
public class LuaCallObject : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallObject')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public class Npc
{
public string Name;
public int Level { get; set; }
public Npc()
{
}
public Npc(string name)
{
Name = name;
}
public string Output()
{
return Name;
}
}
}
lua代码
--lua实例化类
--通过调用构造函数创建对象
local obj = CS.Code.C2L.Npc()
print(obj.Name)
local obj = CS.Code.C2L.Npc("lua")
print(obj.Name)
--调用对象的方法,用“:”不能用“.”,因为对象引用成员变量时,会隐形调用this,等同于lua中的self
print(obj:Output())
--使用lua在unity中实例化GameObject对象,添加一个碰撞体
local box = CS.UnityEngine.GameObject("luaCreate")
box:AddComponent(typeof(CS.UnityEngine.BoxCollider))
输出结果
lua调用结构体
c#代码
namespace Code.C2L
{
public class LuaCallStruct : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallStruct')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public struct TestStruct
{
public string Name;
public string Output()
{
return Name;
}
}
}
lua代码
--和创建对象一样
local obj=CS.Code.C2L.TestStruct()
obj.Name="lua"
print(obj.Name)
print(obj:Output())
输出结果
lua调用枚举
c#代码
namespace Code.C2L
{
public class LuaCallEnum : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallEnum')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public enum TestEnum
{
TotalWar,
Wot
}
}
lua代码
print(CS.Code.C2L.TestEnum.TotalWar)
print(type(CS.Code.C2L.TestEnum.Wot))--userdata
--装换获得枚举值,使用索引获取越界不会报错,使用字符串不存在就会报错
print(CS.Code.C2L.TestEnum.__CastFrom(0))
print(CS.Code.C2L.TestEnum.__CastFrom("Wot"))
输出结果
lua调用对象继承
c#代码
namespace Code.C2L
{
public class LuaCallExtend : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallExtend')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public class TestExtend
{
public void Output()
{
Debug.Log("类本身带的方法");
}
}
[LuaCallCSharp]//类扩展,需要给扩展方法编写的静态类添加,否则lua无法调用到
public static class MyExtend
{
public static void Show(this TestExtend obj)
{
Debug.Log("类扩展实现的方法");
}
}
}
lua代码
local obj=CS.Code.C2L.TestExtend()
obj:Output()
obj:Show()
输出结果
lua调用委托
c#代码
namespace Code.C2L
{
public class LuaCallDelegate : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallDelegate')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public delegate void DelegateLua();
public class TestDelegate
{
public static DelegateLua Static;
public DelegateLua Dynamic;
public static void StaticFunc()
{
Debug.Log("c#静态函数");
}
}
public delegate void EventLua();
public class TestEvent
{
public static event EventLua Static;
public static void StaticFunc()
{
Debug.Log("这是静态函数");
}
public static void CallStatic()
{
Static?.Invoke();
}
public event EventLua Dynamic;
public void CallDynamic()
{
Dynamic?.Invoke();
}
}
}
lua代码
CS.Code.C2L.TestDelegate.Static = CS.Code.C2L.TestDelegate.StaticFunc
CS.Code.C2L.TestDelegate.Static()
--静态委托使用完以后必须要释放
CS.Code.C2L.TestDelegate.Static = nil
local func = function()
print("这是lua的函数")
end
--覆盖添加委托
CS.Code.C2L.TestDelegate.Static = func
--加减操作之前要判断委托是否有值
if (CS.Code.C2L.TestDelegate == nil) then
CS.Code.C2L.TestDelegate.Static = func
else
CS.Code.C2L.TestDelegate.Static = CS.Code.C2L.TestDelegate.Static + func
end
CS.Code.C2L.TestDelegate.Static = CS.Code.C2L.TestDelegate.Static - func
--调用之前应该确定委托有值
if (CS.Code.C2L.TestDelegate ~= nil) then
CS.Code.C2L.TestDelegate.Static()
end
CS.Code.C2L.TestDelegate.Static = nil
local obj=CS.Code.C2L.TestDelegate()
obj.Dynamic=func
obj.Dynamic()
obj.Dynamic=nil
--lua添加事件
CS.Code.C2L.TestEvent.Static("+",CS.Code.C2L.TestEvent.StaticFunc)
CS.Code.C2L.TestEvent.CallStatic()
CS.Code.C2L.TestEvent.Static("-",CS.Code.C2L.TestEvent.StaticFunc)
local func = function()
print("这是lua的函数")
end
local obj=CS.Code.C2L.TestEvent()
obj:Dynamic("+",func)
obj:CallDynamic()
obj:Dynamic("-",func)
输出结果
lua调用泛型
c#代码
namespace Code.C2L
{
public class LuaCallGenericType : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallGenericType')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public class TestGenericType
{
public void Output<T>(T data)
{
Debug.Log("泛型方法:"+data.ToString());
}
public void Output(float data)
{
Output<float>(data);
}
public void Output(string data)
{
Output<string>(data);
}
}
}
lua代码
local obj=CS.Code.C2L.TestGenericType()
obj:Output(123)
obj:Output("lua")
输出结果
lua调用OutRef
c#代码
namespace Code.C2L
{
public class LuaCallOutRef : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('C2L/LuaCallOutRef')");
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public class TestOutRef
{
public static string Func1()
{
return "Func1";
}
public static string Func2(string str1, out string str2)
{
str2 = "Func2 out";
return "Func2";
}
public static string Func3(string str1, ref string str2)
{
str2 = "Func3 ref";
return "Func3";
}
public static string Func4(ref string str1, string str2)
{
str1 = "Func4 ref";
return "Func4";
}
}
}
lua代码
local r1 = CS.Code.C2L.TestOutRef.Func1()
print(r1)
--c# out返回的变量,会赋值给lua的第二个接受返回值的变量
local out2
local r2, out1 = CS.Code.C2L.TestOutRef.Func2("lua", out2)
print(r2, out1, out2)
--c# ref返回的变量,会赋值给lua的第二个接受返回值的变量
local ref2
local r3, ref1 = CS.Code.C2L.TestOutRef.Func3("root", ref2)
print(r3, ref1, ref2)
--即使out ref作为第一个参数,其结果依然会以lua的第二个返回值进行返回
local ref2
local r4, ref1 = CS.Code.C2L.TestOutRef.Func4(ref2, "root")
print(r4, ref1, ref2)
输出结果
C#调用lua
C#调用变量
lua代码
num=100
rate=99.99
isLua=true
name="lua"
c#代码
namespace Code.L2C
{
public class CsharpCallVariable : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('L2C/CsharpCallVariable')");
//luaEnv提供了一个成员变量Global,它可以用于c#获取lua的全局变量
//Global的数据类型是c#实现的luaTable,luaTable的xLua实现的c#和lua中表对应的数据结构
//xLua会将lua中的全局变量以Table的方式全部存储在Global中
//通过运行环境,导出全局变量,类型是luaTable
//luaTable是c#的数据对象,用于和lua中的大G表对应
LuaTable g = XLuaEnv.Instance.Global;
//从lua中将全局变量提取出来,<全局变量的类型>(全局变量的名称)
//如果获取不存在的变量会报错,如果获取类型错误则会使用默认值
int num = g.Get<int>("num");
float rate = g.Get<float>("rate");
bool isLua = g.Get<bool>("isLua");
string name = g.Get<string>("name");
Debug.Log(num + " " + rate + " " + isLua + " " + name);
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
}
输出结果
C#调用方法
lua代码
func1 = function()
print("这是Lua中的func1")
end
func2 = function(name)
print("这是Lua中的func2,参数是:" .. name)
end
func3 = function()
return "这是lua中的func3"
end
func4 = function()
return "这是lua中的func4",100
end
c#代码
namespace Code.L2C
{
public delegate void Func1();
public delegate void Func2(string name);
public delegate string Func3();
[CSharpCallLua]
public delegate void Func4(out string name, out int id);
public class CsharpCallFunction : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('L2C/CsharpCallFunction')");
LuaTable g = XLuaEnv.Instance.Global;
//lua的函数,会导出为c#的委托类型
Func1 func1 = g.Get<Func1>("func1");
func1();
Func2 func2 = g.Get<Func2>("func2");
func2("admin");
Func3 func3 = g.Get<Func3>("func3");
Debug.Log(func3());
Func4 func4 = g.Get<Func4>("func4");
string name;
int id;
func4(out name, out id);
Debug.Log(name + " " + id);
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
}
输出结果
新版本unity使用[CSharpCallLua]不起作用,回头解决一波
C#调用table
lua代码
Core={}
Core.ID=100
Core.Name="root"
Core.IsLua=false
Core.Func1=function (name)
print("这是Core表的Func1函数,接收到c#数据"..name)
end
Core.Func2=function ()
return "这是Core表的Func2函数"
end
Core.Func3=function (self)
print("这是Core表的Func3函数,Core表的成员变量Name是"..self.Name)
end
function Core:Fun4()
print("这是Core表的Func4函数,Core表的成员变量Name是"..self.Name)
end
c#代码
namespace Code.L2C
{
public class CsharpCallTable : MonoBehaviour
{
private void Start()
{
XLuaEnv.Instance.DoString("require('L2C/CsharpCallTable')");
UseStruct();
}
public void UseStruct()
{
LuaTable g = XLuaEnv.Instance.Global;
LuaCore core = g.Get<LuaCore>("Core");
Debug.Log(core.Name);
}
private void OnDestroy()
{
XLuaEnv.Instance.Dispose();
}
}
public delegate string OneStringReturn();
[CSharpCallLua]
public delegate void TransMy(LuaCore table);
public struct LuaCore
{
public int ID;
public string Name;
public bool IsLua;
public OneStringReturn Func1;
public OneStringReturn Func2;
public TransMy Func3;
public TransMy Func4;
}
}