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小时内删除。