上一篇文章
XLua教程之入門篇-CSDN博客
在C#腳本中訪問lua全局數據,特別是table以及function,代價比較大,建議盡量少做相關操作。
LuaEnv.Global.Get
用于獲取一個全局變量,但是無法獲取局部變量(用local修飾)
全局基本類型變量
支持int、float、double、bool、string類型
string value1 = luaenv.Global.Get<string>("stringValue");
Debug.Log($"string:{value1}");float value2 = luaenv.Global.Get<float>("floatValue");
Debug.Log($"float:{value2}");bool value3 = luaenv.Global.Get<bool>("boolValue");
Debug.Log($"bool:{value3}");double value4 = luaenv.Global.Get<double>("doubleValue");
Debug.Log($"double:{value4}");int value5 = luaenv.Global.Get<int>("intValue");
Debug.Log($"int:{value5}");
全局函數
測試:Lua腳本側代碼
--無參無返回值
function SayHi()print("hello world!")
end--有參有返回值
function GetNumSum(a,b,c)local result = a+b+c;print(result)return result
end--變長參數多返回值
function GetManyResult(...)local list = {...}local result1 = 0;for _,v in ipairs(list) doresult1 = result1 + vendlocal result2 = 1;for _,v in ipairs(list) doresult2 = result2 * vendreturn result1,result2
end
第一種方法? 映射到委托delegate(推薦使用)
這種是建議的方式,性能好很多,而且類型安全。缺點是要生成代碼(如果沒生成代碼會拋InvalidCastException異常)
1、先注冊對應Lua函數的C#委托,并添加 [CSharpCallLua]標簽。(無參無返回值可以不用添加該標簽,xlua默認支持)
//無參無返回值
public delegate void NoParamNoReturn();//有參有返回值
[CSharpCallLua]
public delegate int XParamOneReturn(int a,int b,int c);//變長參數1返回值
[CSharpCallLua]
public delegate int XParam1Return(params int[] temp);
2、先清空生成的xlua插樁代碼,再重新生成
3、調用
//無參無返回值
NoParamNoReturn func1 = luaEnv.Global.Get<NoParamNoReturn>("SayHi");
func1();//有參有返回值
XParamOneReturn func2 = luaEnv.Global.Get<XParamOneReturn>("GetNumSum");
var result1 = func2(1,2,3);
Debug.Log(result1);//變長參數1返回值
XParam1Return func3 = luaEnv.Global.Get<XParam1Return>("GetManyResult1");
int a =default(int);
int b =default(int);
var result2 = func3(1,2,3,4);
Debug.Log(result2);
第二種方法? 映射到LuaFunction
LuaFunction上有個變參的Call函數,可以傳任意類型,任意個數的參數,返回值是object的數組,對應于lua的多返回值。
//無參無返回值
LuaFunction func1 = luaEnv.Global.Get<LuaFunction>("SayHi");
func1.Call();//有參有返回值
LuaFunction func2 = luaEnv.Global.Get<LuaFunction>("GetNumSum");
var result1 = func2.Call(1,2,3);
foreach (var item in result1)
{Debug.Log(item);
}//變長參數多返回值
LuaFunction func3 = luaEnv.Global.Get<LuaFunction>("GetManyResult");
var result2 = func3.Call(1,2,3);
foreach (var item in result2)
{Debug.Log(item);
}
對比:
優先使用映射到委托方案
映射到XLua自帶的LuaFunction,簡單方便,但是會消耗性能;
映射到Delegate委托,官方建議,性能比LuaFunction要好很多,而且類型安全;但需要在自定義委托前添加[CSharpCallLua]特性標簽
特性 | 映射到委托 (Delegate) | 映射到 LuaFunction |
---|---|---|
性能 | 極高?(接近原生C#調用) | 較低?(涉及查找、壓參、調用、返回等一系列開銷) |
用法 | 像調用普通C#委托一樣 | 調用其?Call(...) ?方法,傳入參數數組 |
類型安全 | 強類型,編譯時檢查參數和返回值類型 | 弱類型,參數和返回值都是?object[] ,運行時易出錯 |
內存開銷 | 小 | 較大(每次調用可能產生臨時?object[] ?垃圾) |
適用場景 | 高頻調用(如?Update 、UI事件回調) | 低頻調用、一次性調用、參數數量/類型不固定 |
配置要求 | 需要標記?[CSharpCallLua] ?并生成代碼 | 無需任何額外配置,開箱即用 |
全局表
根據表的數據結構類型可以按照不同的情況,選擇不同的映射形式。
如果表的形式類似于列表,可以映射到C#的List<T>。
如果表的形式類似于字典,可以映射到C#的Dictionary<T>。
如果表的形式類似于類,可以映射到C#的class。
映射到List<T>
List<int> list1 = luaEnv.Global.Get<List<int>>("list1");
foreach (var item in list1)
{Debug.Log(item);
}
映射到Dictionary<T>
Dictionary<int, string> dic = luaEnv.Global.Get<Dictionary<int, string>>("list2");
foreach (var item in dic)
{Debug.Log($"{item.Key}:{item.Value}");
}
映射到class
先根據lua表,聲明對應C#類結構,再調用
public class Student
{public int id;public string name;public bool sex;public float score;
}Student student = luaEnv.Global.Get<Student>("Student");
Debug.Log($"{student.id} {student.name} {student.sex} {student.score}");
映射到LuaTable
xLua自帶映射,兼容Lua表多種情況,不用定義c#類結構,開箱即用。但是性能消耗比較大,一般情況不推薦使用。
LuaTable student = luaEnv.Global.Get<LuaTable>("Student");
Debug.Log($"{student.Get<int>("id")}");
Debug.Log($"{student.Get<string>("name")}");
Debug.Log($"{student.Get<bool>("sex")}");
Debug.Log($"{student.Get<float>("score")}");
LuaEnv.Global.Set
用于修改一個全局變量
//string
luaenv.Global.Set("stringValue", "天天向上");
//float
luaenv.Global.Set("floatValue", 99.99);
//bool
luaenv.Global.Set("boolValue", false);
//double
luaenv.Global.Set("doubleValue", 9.999999999);
//int
luaenv.Global.Set("intValue", 438);