UnityXLua官⽅教程学习
⼀、Lua ⽂件加载
1. 执⾏字符串
1using UnityEngine;
2using XLua;
3
4public class ByString : MonoBehaviour {
5 LuaEnv luaenv = null;
6// Use this for initialization
7void Start () {
8 luaenv = new LuaEnv();
9// 执⾏代码块,输出 hello world
10 luaenv.DoString("print('hello world')");
11 }
12
13// Update is called once per frame
14void Update () {
15if (luaenv != null)
16 {
17// 清楚 Lua 未⼿动释放的 LuaBase 对象
18 luaenv.Tick();
19 }
20 }
21
22void OnDestroy()
23 {
24// 销毁
25 luaenv.Dispose();
26 }
27 }
其中 Dostring 函数返回值即为代码块⾥ return 语句的返回值。
2. 加载 Lua ⽂件
1 luaenv = new LuaEnv();
2// 加载 byfile Lua ⽂件
3 luaenv.DoString("require 'byfile'");
其中 Lua ⽂件代码为:
print('hello world')
需要注意的是因为 Resource 只⽀持有限的后缀,放 Resources 下 lua ⽂件得加上 txt 后缀,如:。
3. ⾃定义 Loader
1void Start()
2 {
3 luaenv = new LuaEnv();
4// ⾃定义 loader
5 luaenv.AddLoader((ref string filename) => {
6// 若要加载 InMemory
7if (filename == "InMemory")
8 {
9string script = "return {ccc = 9999}";
10// 将字符串转换成byte[]
11return System.Text.Encoding.UTF8.GetBytes(script);
12 }
13return null;
14 });
15// 执⾏代码块,访问table中的常量ccc
16 luaenv.DoString("print('=', require('InMemory').ccc)");
17 }
通过 Addloader 可以注册个回调,该回调参数是字符串,返回⼀个 byte 数组。lua 代码⾥调⽤ require 时,参数就会传给回调。 注意,require 返回⼀个由模块常量和函数组成的table。
⼆、C# 访问 Lua
其中 lua 代码如下:
1 a = 1
2 b = 'hello world'
3 c = true
4
5 d = {
6 f1 = 12, f2 = 34,
71, 2, 3,
8 add = function(self, a, b)
9print('d.add called')
10return a + b
11end
12 }
13
14function e()
15print('i am e')
16end
17
18function f(a, b)
19print('a', a, 'b', b)
20return1, {f1 = 1024}
21end
22
23function ret_e()
24print('ret_e called')
25return e
26end
其中包含常量,表和函数。C# 代码如下:
1public class DClass
2 {
3public int f1; // 属性与Xlua⾥的对应
4public int f2;
5 }
6
7 [CSharpCallLua]
unity 教程8public interface ItfD
9 {
10int f1 { get; set; }
11int f2 { get; set; }
12int add(int a, int b);
13 }
14
15// ⽣成代码
16// 若有多个参数,可⽤ out 属性接收剩下的返回
17 [CSharpCallLua]
18public delegate int FDelegate(int a, string b, out DClass c);
19
20 [CSharpCallLua]
21public delegate Action GetE();
22
23// Use this for initialization
24void Start()
25 {
26 luaenv = new LuaEnv();
27 luaenv.DoString(script);
28
29// 访问全局常量
30 Debug.Log("_G.a = " + luaenv.Global.Get<int>("a")); // 1
31 Debug.Log("_G.b = " + luaenv.Global.Get<string>("b")); // hello world
32 Debug.Log("_G.c = " + luaenv.Global.Get<bool>("c")); // Ture
33
34// 访问全局的 table
35// 映射到普通的class或struct
36//映射到有对应字段的class,值拷贝,class字段的修改不会影响到table,反之也不会
37 DClass d = luaenv.Global.Get<DClass>("d");
38 Debug.Log("_G.d = {f1=" + d.f1 + ", f2=" + d.f2 + "}"); // 12 34
39
40// 映射有 key 的
41 Dictionary<string, double> d1 = luaenv.Global.Get<Dictionary<string, double>>("d");//映射到Dictionary<string, double>,值拷贝
42 Debug.Log("_G.d = {f1=" + d1["f1"] + ", f2=" + d1["f2"] + "}, d.Count=" + d1.Count); // 12 34 2
43
44// 映射没有 key 的
45 List<double> d2 = luaenv.Global.Get<List<double>>("d"); //映射到List<double>,值拷贝
46 Debug.Log("_G.d.len = " + d2.Count); // 3
47
48// 映射到⼀个 interface
49// 要在 interface 定义前加 [CSharpCallLua]
50 ItfD d3 = luaenv.Global.Get<ItfD>("d"); //映射到interface实例,by ref,这个要求interface加到⽣成列表,否则会返回null,建议⽤法
51 d3.f2 = 1000; // 外部修改会影响 Lua 内的值
52 Debug.Log("_G.d = {f1=" + d3.f1 + ", f2=" + d3.f2 + "}"); // 12 1000
53 Debug.Log("_G.d:add(1, 2)=" + d3.add(1, 2)); // d.add called
54
55//映射到LuaTable,by ref
56 LuaTable d4 = luaenv.Global.Get<LuaTable>("d");
57 Debug.Log("_G.d = {f1=" + d4.Get<int>("f1") + ", f2=" + d4.Get<int>("f2") + "}");
58
59// 访问⼀个全局的函数
60// 映射到 delegate
61 Action e = luaenv.Global.Get<Action>("e");//映射到⼀个delgate,要求delegate加到⽣成列表,否则返回null,建议⽤法
62 e(); // i am e
63
64 FDelegate f = luaenv.Global.Get<FDelegate>("f");
65 DClass d_ret;
66// 多值返回,可⽤out接收多余的参数
67// 输出 a 100 b John
68int f_ret = f(100, "John", out d_ret);//lua的多返回值映射:从左往右映射到c#的输出参数,输出参数包括返回值,out参数,ref参数
69// table只含有常量f1,所以f2赋值为0
70 Debug.Log("ret.d = {f1=" + d_ret.f1 + ", f2=" + d_ret.f2 + "}, ret=" + f_ret); // 1024 0 1
71
72 GetE ret_e = luaenv.Global.Get<GetE>("ret_e");//delegate可以返回更复杂的类型,甚⾄是另外⼀个delegate
73 e = ret_e();
74 e();
75
76// 映射到 LuaFunction
77 LuaFunction d_e = luaenv.Global.Get<LuaFunction>("e");
78// Call 函数可以传任意类型,任意个数的参数
79 d_e.Call();
80
81 }
访问 lua 全局数据,特别是 table 以及 function,代价⽐较⼤,建议尽量少做,⽐如在初始化时调⽤获取⼀次后,保存下来,后续直接使⽤即可。
三、Lua 调⽤ C#
其中 C# 代码如下:
1namespace Tutorial
2 {
3 [LuaCallCSharp]
4public class BaseClass
5 {
6public static void BSFunc()
7 {
8 Debug.Log("Driven Static Func, BSF = "+ BSF);
9 }
10
11public static int BSF = 1;
12
13public void BMFunc()
14 {
15 Debug.Log("Driven Member Func, BMF = " + BMF);
16 }
17
18public int BMF { get; set; }
19 }
20
21public struct Param1
22 {
23public int x;
24public string y;
25 }
26
27 [LuaCallCSharp]
28public enum TestEnum
29 {
30 E1,
31 E2
32 }
33
34 [LuaCallCSharp]
35public class DrivenClass : BaseClass
36 {
37 [LuaCallCSharp]
38public enum TestEnumInner
39 {
40 E3,
41 E4
42 }
43
44public void DMFunc()
45 {
46 Debug.Log("Driven Member Func, DMF = " + DMF);
47 }
48
49public int DMF { get; set; }
50
51public double ComplexFunc(Param1 p1, ref int p2, out string p3, Action luafunc, out Action csfunc)
52 {
53 Debug.Log("P1 = {x=" + p1.x + ",y=" + p1.y + "},p2 = "+ p2);
54 luafunc();
55 p2 = p2 * p1.x;
56 p3 = "hello " + p1.y;
57 csfunc = () =>
58 {
59 Debug.Log("csharp callback invoked!");
60 };
61return1.23;
62 }
63
64public void TestFunc(int i)
65 {
66 Debug.Log("TestFunc(int i)");
67 }
68
69public void TestFunc(string i)
70 {
71 Debug.Log("TestFunc(string i)");
72 }
73
74public static DrivenClass operator +(DrivenClass a, DrivenClass b)
75 {
76 DrivenClass ret = new DrivenClass();
77 ret.DMF = a.DMF + b.DMF;
78return ret;
79 }
80
81public void DefaultValueFunc(int a = 100, string b = "cccc", string c = null)
82 {
83 UnityEngine.Debug.Log("DefaultValueFunc: a=" + a + ",b=" + b + ",c=" + c);
84 }
85
86public void VariableParamsFunc(int a, params string[] strs)
87 {
88 UnityEngine.Debug.Log("VariableParamsFunc: a =" + a);
89foreach (var str in strs)
90 {
91 UnityEngine.Debug.Log("str:" + str);
92 }
93 }
94
95public TestEnum EnumTestFunc(TestEnum e)
96 {
97 Debug.Log("EnumTestFunc: e=" + e);
98return TestEnum.E2;
99 }
100
101public Action<string> TestDelegate = (param) =>
102 {
103 Debug.Log("TestDelegate in c#:" + param);
104 };
105
106public event Action TestEvent;
107
108public void CallEvent()
109 {
110 TestEvent();
111 }
112
113public ulong TestLong(long n)
114 {
115return (ulong)(n + 1);
116 }
117
118class InnerCalc : ICalc
119 {
120public int add(int a, int b)
121 {
122return a + b;
123 }
124
125public int id = 100;
126 }
127
128public ICalc GetCalc()
129 {
130return new InnerCalc();
131 }
132
133public void GenericMethod<T>()
134 {
135 Debug.Log("GenericMethod<" + typeof(T) + ">");
136 }
137 }
138
139 [LuaCallCSharp]
140public interface ICalc
141 {
142int add(int a, int b);
143 }
144
145 [LuaCallCSharp]
146public static class DrivenClassExtensions
147 {
148public static int GetSomeData(this DrivenClass obj)
149 {
150 Debug.Log("GetSomeData ret = " + obj.DMF);
151return obj.DMF;
152 }
153
154public static int GetSomeBaseData(this BaseClass obj)
155 {
156 Debug.Log("GetSomeBaseData ret = " + obj.BMF);
157return obj.BMF;
158 }
159
160public static void GenericMethodOfString(this DrivenClass obj)
161 {
162 obj.GenericMethod<string>();
163 }
164 }
165 }
其中可变参数可⽤params string[] strs 实现。要在 Lua 直接访问什么,记得在定义前加上 [LuaCallCSharp] 对应的 lua 代码为:
1function demo()
2-- new C#对象
3-- 没有new,所有C#相关的都放在CS下
4local newGameObj = CS.UnityEngine.GameObject()
5-- 创建⼀个名为helloworld的物体
6local newGameObj2 = CS.UnityEngine.GameObject('helloworld')
7print(newGameObj, newGameObj2)
8
9--访问静态属性,⽅法
10local GameObject = CS.UnityEngine.GameObject
11print('UnityEngine.Time.deltaTime:', CS.UnityEngine.Time.deltaTime) --读静态属性
12 CS.UnityEngine.Time.timeScale = 0.5--写静态属性
13-- 查物体 helloworld
14print('helloworld', GameObject.Find('helloworld')) --静态⽅法调⽤
15
16--访问成员属性,⽅法
17local DrivenClass = CS.Tutorial.DrivenClass
18local testobj = DrivenClass()
19 testobj.DMF = 1024--设置成员属性
20print(testobj.DMF)--读取成员属性
21-- 输出 DMF=1024
22 testobj:DMFunc()--成员⽅法使⽤冒号
23
24--基类属性,⽅法
25print(DrivenClass.BSF)--读基类静态属性 1
26 DrivenClass.BSF = 2048--写基类静态属性
27 DrivenClass.BSFunc();--基类静态⽅法 2048
28-- BMF 初始为0
29print(testobj.BMF)--读基类成员属性 0
30 testobj.BMF = 4096--写基类成员属性
31 testobj:BMFunc()--基类⽅法调⽤ 4096
32
33--复杂⽅法调⽤
34-- 参数处理规则:C#的普通参数和ref修饰的算⼀个参数,out不算,从左往右顺序
35-- 返回值处理规则:返回值(如果有)算第⼀个,out,ref修饰的参数算⼀个,从左往右
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论