文件加载 使用LuaEnv中的DoString方法来执行Lua脚本。 因为创建一个LuaEnv相当于创建了一个lua虚拟机,所以一个游戏最好只有一个LuaEnv。
env.DoString("print(\"Hello World\")" ); TextAsset ta = Resources.Load<TextAsset>("Lua/helloworld.lua" ); env.DoString(ta.text); env.DoString("require 'Lua/helloworld'" ); private byte [] LuaLoader (ref string filePath ){ string path = "Lua/" + filePath + ".lua" ; print(path); TextAsset ta = Resources.Load<TextAsset>(path); return System.Text.Encoding.UTF8.GetBytes(ta.text); } env.AddLoader(LuaLoader); env.DoString("require 'helloworld'" );
官方建议的加载Lua脚本方式是:整个程序就一个DoString(“require ‘main’”),然后在main.lua加载其它脚本(类似lua脚本的命令行执行:lua main.lua)。
C#访问Lua普通全局变量 先加载lua脚本,再通过LuaEnv.Global.Get获取变量。
TextAsset ta = Resources.Load<TextAsset>("Lua/variable.lua" ); env.DoString(ta.text); int g_int = env.Global.Get<int >("g_int" );string g_str = env.Global.Get<string >("g_str" );bool g_bool = env.Global.Get<bool >("g_bool" );
C#访问Lua table的四种方法 需要注意的是,在构建C#中对应的结构时,接口一定要是public修饰,否则会报错。类最好也是,但是经测试,没有报错。
映射到普通class或struct
table的属性可以多于或者少于class的属性,也就是不一定都需要做映射。这个过程是值拷贝,如果class比较复杂代价会比较大。而且修改class的字段值不会同步到table,反过来也不会。
public class Person { public string name; public int age; } Person p = env.Global.Get<Person>("g_tbl" );
映射到接口
一定要加[CSharpCallLua]和public,否则会报错。
g_int = 1 g_str = "Hello World Variable" g_bool = false g_tbl = {name = "Juhnny" , age = 12 } g_tbl.say = function (this, str) print (str) end
[CSharpCallLua ] public interface IPerson { string name { get ; set ; } int age { get ; set ; } public void say (string str ) ; } IPerson p = env.Global.Get<IPerson>("g_tbl" ); p.say("Yahoo" );
映射到Dictionary和List
这种方法较方法2更为轻量级,但是要求table下key和value类型一致。
g_dic = {apple = "iPhone" , flower = "Huawei" } g_list = {1 , 3 , 5 , 7 , 9 }
Dictionary<string , string > dic = env.Global.Get<Dictionary<string , string >>("g_dic" ); foreach (var child in dic){ print(string .Format("Key is {0}, Value is {1}" , child.Key, child.Value)); } List<int > list = env.Global.Get<List<int >>("g_list" ); foreach (var v in list){ print(v); }
映射到LuaTable
这种方法比较慢,而且没有类型检查,不推荐使用。
LuaTable tab = env.Global.Get<LuaTable>("g_tbl" ); string name = tab.Get<string >("name" );int age = tab.Get<int >("age" );print(string .Format("Name is {0}, age is {1}" , name, age)); foreach (string key in tab.GetKeys()){ print(tab.Get<object >(key)); }
C#访问Lua全局函数 使用delegate映射
这种是建议的方式,性能好很多,而且类型安全,但是要生成代码。支持带返回值,多返回值,甚至返回值都可以是delegate。
g_func1 = function () print ("FF" ) end g_func2 = function (num) print (num) return num, "Yoshida" , "SE" end
[CSharpCallLua ] public delegate int Func2 (int num, out string name, out string company ) ;Action func1 = env.Global.Get<Action>("g_func1" ); func1(); func1 = null ; Func2 func2 = env.Global.Get<Func2>("g_func2" ); int num = func2(14 );func2 = null Func2 func2 = env.Global.Get<Func2>("g_func2" ); string name;string company;int num = func2(14 , out name, out company);func2 = null
在过去的一些版本中,需要在不使用后,将接收到的函数销毁,否则会在LuaEnv.Dispose的时候报错。
使用LuaFunction
与上一种方法优缺点相反,不推荐使用。
LuaFunction func = env.Global.Get<LuaFunction>("g_func2" ); object [] res = func.Call(14 );
Lua调用C# CS.UnityEngine.Time.deltaTime CS.UnityEngine.Time.timeScale = 0.5 CS.UnityEngine.GameObject.Find('helloworld' ) testobj:DMFunc()
其它注意事项 方法的参数处理 Lua调用侧的参数处理规则:C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,然后从左往右对应lua 调用侧的实参列表。
Lua调用侧的返回值处理规则:C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,ref算一个返回值,然后从左往右对应lua的多返回值。
可变参数的处理
void VariableParamsFunc (int a, params string [] strs )testobj:VariableParamsFunc (5 , 'hello' , 'john' )
枚举
testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1) 上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的。 枚举类支持__CastFrom方法,可以实现从一个整数或者字符串到枚举值的转换,例如: CS.Tutorial.TestEnum.__CastFrom(1 ) CS.Tutorial.TestEnum.__CastFrom('E1' )
委托
testobj:TestEvent('+' , lua_event_callback) testobj:TestEvent('-' , lua_event_callback)