马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
在Xlua中,利用[GCOptimize]可以制止C#和Lua间通报值范例(平凡值范例,只包罗值范例的strcut或嵌套struct,罗列范例,以及它们构成的数组)时发生gc alloc
lua脚本
- function id(...)
- return ...
- end
- function add(a, b) return a + b end
- function array_exchange(arr)
- arr[0], arr[1] = arr[1], arr[0]
- end
- local v3 = CS.UnityEngine.Vector3(7, 8, 9)
- local vt = CS.XLuaTest.MyStruct(5, 6)
- function lua_access_csharp()
- monoBehaviour:FloatParamMethod(123) --primitive
- monoBehaviour:Vector3ParamMethod(v3) --vector3
- local rnd = math.random(1, 100)
- local r = monoBehaviour:Vector3ParamMethod({x = 1, y = 2, z = rnd}) --vector3
- assert(r.x == 1 and r.y == 2 and r.z == rnd)
- monoBehaviour:StructParamMethod(vt) --custom struct
- r = monoBehaviour:StructParamMethod({a = 1, b = rnd, e = {c = rnd}})
- assert(r.b == rnd and r.e.c == rnd)
- monoBehaviour:EnumParamMethod(CS.XLuaTest.MyEnum.E2) --enum
- monoBehaviour:DecimalParamMethod(monoBehaviour.a5[0])
- monoBehaviour.a1[0], monoBehaviour.a1[1] = monoBehaviour.a1[1], monoBehaviour.a1[0] -- field
- end
- exchanger = {
- exchange = function(self, arr)
- array_exchange(arr)
- end
- }
- A = { B = { C = 789}}
- GDATA = 1234;
复制代码 表明
这段代码是Lua脚本的示例,团结了与C#交互的一些功能。让我们逐个表明:
- 函数 id(...) 和 add(a, b):
- id(...) 函数是一个不定参数的函数,它返回吸取到的全部参数。
- add(a, b) 函数简朴地盘算两个参数的和并返回效果。该
这两个函数的目的是要测试让数据从C#传入lua再传回C#,观察gc情况
- 函数 array_exchange(arr):
- 这个函数交换了数组 arr 的第一个和第二个元素的位置。Lua中的数组索引从1开始,因此 arr[0] 实际上是 arr[1],arr[1] 是 arr[2]。
该函数利用了lua的等号特性,本质是一个swap函数,而且只交换arr的头两个数据
- 界说了两个变量 v3 和 vt:
- v3 是一个利用C#的Unity引擎的 Vector3 布局体,体现一个三维向量 (7, 8, 9)。
- vt 是一个自界说的布局体 MyStruct 的实例,此中包罗字段 (5, 6)。
- 函数 lua_access_csharp():
- 这个函数演示了如安在Lua中访问和调用C#中的方法和字段:
- monoBehaviour:FloatParamMethod(123) 调用了一个担当单精度浮点数参数的方法。
- monoBehaviour:Vector3ParamMethod(v3) 通报了一个 Vector3 范例的参数给一个担当 Vector3 的方法。
- 利用 math.random(1, 100) 天生一个随机数 rnd,然后通报给一个担当 Vector3 参数的方法,并验证返回的效果。
- monoBehaviour:StructParamMethod(vt) 通报了一个自界说布局体范例的参数。
- 类似地,通报一个包罗字段的表给一个担当布局体参数的方法,并验证返回效果。
- monoBehaviour:EnumParamMethod(CS.XLuaTest.MyEnum.E2) 通报了一个罗列范例的参数。
- monoBehaviour
ecimalParamMethod(monoBehaviour.a5[0]) 通报了一个十进制数参数。
- 末了一行交换了一个数组 monoBehaviour.a1 的两个元素的位置。
monoBehaviour是在C#中set的变量,即this,以是这里是在利用C#函数处置惩罚lua对象
- 变量 exchanger:
- exchanger 是一个包罗 exchange 方法的表,该方法担当一个数组参数并调用 array_exchange 函数来交换数组的两个元素。
该表在C#中创建有对应函数的接口获取,通过C#的接口调用其方法
- 全局变量 A 和 GDATA:
- A 是一个嵌套表布局,此中包罗 B 字段,B 字段包罗 C 字段。
- GDATA 是一个全局变量,存储整数值 1234。
这两个变量会在C#中每次取出,而且 + 1放回
C#调用过程
- [GCOptimize]
- [LuaCallCSharp]
- public struct Pedding
- {
- public byte c;
- }
- [GCOptimize]
- [LuaCallCSharp]
- public struct MyStruct
- {
- public int a;
- public int b;
- public decimal c;
- public Pedding e;
- }
- [LuaCallCSharp]
- public enum MyEnum
- {
- E1,
- E2
- }
复制代码 利用GCOptimize优化只有值范例的Struct以及嵌套Struct
利用LuaCallCSharp指示Lua可以调用这些Struct
- [CSharpCallLua]
- public delegate int IntParam(int p);
- [CSharpCallLua]
- public delegate Vector3 Vector3Param(Vector3 p);
- [CSharpCallLua]
- public delegate MyStruct CustomValueTypeParam(MyStruct p);
- [CSharpCallLua]
- public delegate MyEnum EnumParam(MyEnum p);
- [CSharpCallLua]
- public delegate decimal DecimalParam(decimal p);
- [CSharpCallLua]
- public delegate void ArrayAccess(Array arr);
- [CSharpCallLua]
- public interface IExchanger
- {
- void exchange(Array arr);
- }
复制代码 创建一系列delegate吸取Lua函数,以及一个接口吸取lua的表
以上都是类外的前期声明准备,接下来是在类中的字段界说
起首最告急的一点是,类要加上LuaCallCSharp的标签,由于反面会在内里向Lua传入自己的this指针,因此lua是可以调用类的
在类中,先界说一些等会要用到的妙妙工具(字段)
- IntParam f1;
- Vector3Param f2;
- CustomValueTypeParam f3;
- EnumParam f4;
- DecimalParam f5;
- ArrayAccess farr;
- Action flua;
- IExchanger ie;
- LuaFunction add;
- [NonSerialized]
- public double[] a1 = new double[] { 1, 2 };
- [NonSerialized]
- public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };
- [NonSerialized]
- public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };
- [NonSerialized]
- public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
- [NonSerialized]
- public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };
复制代码 前五个委托吸取Lua的id函数,差别的值范例数据都测了一遍(从C#传lua再传返来)
farr吸取lua的交换函数,传入数组,交换数组头两个元素,再传返来
flua吸取lua_access_csharp()函数,负责触发lua去访问c#的变量和函数
ie传入表exchanger,并通过内里的函数去访问交换函数(同2)
add是用LuaFunction对象创建的,可以通过add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult> 的方式访问。
反面的a1 ~ a5则是为交换函数准备的差别范例的数组
- luaenv.DoString(script);
- luaenv.Global.Set("monoBehaviour", this);
- luaenv.Global.Get("id", out f1);
- luaenv.Global.Get("id", out f2);
- luaenv.Global.Get("id", out f3);
- luaenv.Global.Get("id", out f4);
- luaenv.Global.Get("id", out f5);
- luaenv.Global.Get("array_exchange", out farr);
- luaenv.Global.Get("lua_access_csharp", out flua);
- luaenv.Global.Get("exchanger", out ie);
- luaenv.Global.Get("add", out add);
- luaenv.Global.Set("g_int", 123);
- luaenv.Global.Set(123, 456);
- int i;
- luaenv.Global.Get("g_int", out i);
- Debug.Log("g_int:" + i);
- luaenv.Global.Get(123, out i);
- Debug.Log("123:" + i);
复制代码 接下来先在luaenv中运行脚本,再将对应的值提取到C#字段中,详细对应关系上一段已经说了
- // c# call lua function with value type but no gc (using delegate)
- //仅仅传递数值再返回C#中
- f1(1); // primitive type
- f2(new Vector3(1, 2, 3)); // vector3
- MyStruct mystruct1 = new MyStruct(5, 6);
- f3(mystruct1); // custom complex value type
- f4(MyEnum.E1); //enum
- decimal dec1 = -32132143143100109.00010001010M;
- f5(dec1); //decimal
- // using LuaFunction.Func<T1, T2, TResult>
- //使用LuaFunction风格的函数触发
- add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult>
- // lua access c# value type array no gc
- //传递数组进去并交换头两个数的位置再传回来
- farr(a1); //primitive value type array
- farr(a2); //vector3 array
- farr(a3); //custom struct array
- farr(a4); //enum arry
- farr(a5); //decimal arry
- // lua call c# no gc with value type
- //让lua侧调用C#变量
- flua();
- //c# call lua using interface
- //使用接口风格调用表中的交换数组头两个元素的函数
- ie.exchange(a2);
- //no gc LuaTable use
- //直接设置获取lua中的值的数
- luaenv.Global.Set("g_int", 456);
- int i;
- luaenv.Global.Get("g_int", out i);
- luaenv.Global.Set(123.0001, mystruct1);
- MyStruct mystruct2;
- luaenv.Global.Get(123.0001, out mystruct2);
- decimal dec2 = 0.0000001M;
- luaenv.Global.Set((byte)12, dec1);
- luaenv.Global.Get((byte)12, out dec2);
- //这两个是lua中定义的值和嵌套表,访问和修改其也不会产生gc
- int gdata = luaenv.Global.Get<int>("GDATA");
- luaenv.Global.SetInPath("GDATA", gdata + 1);
- int abc = luaenv.Global.GetInPath<int>("A.B.C");
- luaenv.Global.SetInPath("A.B.C", abc + 1);
- //lua手动gc函数
- luaenv.Tick();
复制代码 这一段代码是Update中的,会每帧实行,重要是展示大量通报数据下不会产生gc alloc
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |