找回密码
 立即注册
查看: 418|回复: 0

xlua学习4 值传递避免gc

[复制链接]
发表于 2021-8-11 20:33 | 显示全部楼层 |阅读模式
定义方法

声明一些方法,结构体,接口,作为测试对象
对于只包含值类型的结构体我们可以加GCOptimize标签,让xlua生成代码,优化gc
不要忘记在xlua中生成代码
  1. [GCOptimize]//只包含值类型的结构体,可以打GCOptimize标签,并生成代码,优化gc
  2. [LuaCallCSharp]//lua中使用C#,打标签生成代码做优化,否则会使用反射的方式访问,非常耗资源
  3.                //测试结构体
  4. public struct Pedding
  5. {
  6.     public byte c;
  7. }
  8. [GCOptimize]
  9. [LuaCallCSharp]
  10. //测试结构体
  11. public struct MyStruct
  12. {
  13.     public MyStruct(int p1, int p2)
  14.     {
  15.         a = p1;
  16.         b = p2;
  17.         c = p2;
  18.         e.c = (byte)p1;
  19.     }
  20.     public int a;
  21.     public int b;
  22.     public decimal c;
  23.     public Pedding e;
  24. }
  25. [LuaCallCSharp]
  26. //测试枚举
  27. public enum MyEnum
  28. {
  29.     E1,
  30.     E2
  31. }
  32. [CSharpCallLua]
  33. public delegate int IntParam(int p);//测试方法
  34. [CSharpCallLua]
  35. public delegate Vector3 Vector3Param(Vector3 p);//测试方法
  36. [CSharpCallLua]
  37. public delegate MyStruct CustomValueTypeParam(MyStruct p);//测试方法
  38. [CSharpCallLua]
  39. public delegate MyEnum EnumParam(MyEnum p);//测试方法
  40. [CSharpCallLua]
  41. public delegate decimal DecimalParam(decimal p);//测试方法
  42. [CSharpCallLua]
  43. public delegate void ArrayAccess(Array arr);//测试方法
  44. [CSharpCallLua]
  45. //测试接口
  46. public interface IExchanger
  47. {
  48.     void exchange(Array arr);
  49. }
复制代码
然后创建实例和一些测试数据
  1. IntParam f1;//测试方法
  2. Vector3Param f2;
  3. CustomValueTypeParam f3;
  4. EnumParam f4;
  5. DecimalParam f5;
  6. ArrayAccess farr;
  7. IExchanger ie;
  8. Action flua;
  9. LuaFunction add;
  10. #endregion
  11. #region test data
  12. [NonSerialized]
  13. public double[] a1 = new double[] { 1, 2 };//测试数据
  14. [NonSerialized]
  15. public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };
  16. [NonSerialized]
  17. public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };
  18. [NonSerialized]
  19. public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
  20. [NonSerialized]
  21. public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };
复制代码
接下来定义几个方法供lua调用测试
  1. [LuaCallCSharp]
  2. public float FloatParamMethod(float p)
  3. {
  4.     return p;
  5. }
  6. [LuaCallCSharp]
  7. public Vector3 Vector3ParamMethod(Vector3 p)
  8. {
  9.     return p;
  10. }
  11. [LuaCallCSharp]
  12. public MyStruct StructParamMethod(MyStruct p)
  13. {
  14.     return p;
  15. }
  16. [LuaCallCSharp]
  17. public MyEnum EnumParamMethod(MyEnum p)
  18. {
  19.     return p;
  20. }
  21. [LuaCallCSharp]
  22. public decimal DecimalParamMethod(decimal p)
  23. {
  24.     return p;
  25. }
复制代码
编写lua测试代码

在lua中根据刚刚定义的数据结构,生成表和方法
  1. A = { B = { C = 789}};--定义一个结构体
  2. GDATA = 1234;--定义一个num类型
  3. local v3 = CS.UnityEngine.Vector3(7, 8, 9);--调用c#类中的参数
  4. local vt = CS.MyStruct(5, 6);--调用c#类中的参数
  5. --相当于泛型
  6. function id(...)
  7.         return ...;
  8. end
  9. --简单的相加方法
  10. function add(a, b)
  11.         return a + b ;
  12. end
  13. --数组index0 和 index1的交换
  14. function array_exchange(arr)
  15.         arr[0], arr[1] = arr[1], arr[0];
  16. end
  17. --测试访问C#中的方法
  18. function lua_access_csharp()
  19.         self:FloatParamMethod(123); --primitive
  20.         self:Vector3ParamMethod(v3); --vector3
  21.         local rnd = math.random(1, 100);
  22.         local r = self:Vector3ParamMethod({x = 1, y = 2, z = rnd}); --vector3
  23.         assert(r.x == 1 and r.y == 2 and r.z == rnd);
  24.         self:StructParamMethod(vt); --custom struct
  25.         r = self:StructParamMethod({a = 1, b = rnd, e = {c = rnd}});
  26.         assert(r.b == rnd and r.e.c == rnd);
  27.         self:EnumParamMethod(CS.MyEnum.E2); --enum
  28.         self:DecimalParamMethod(self.a5[0]);
  29.         self.a1[0], self.a1[1] = self.a1[1], self.a1[0]; -- field
  30. end
  31. --对应C#类中的IExchanger接口
  32. exchanger = {
  33.         exchange = function(self, arr)
  34.                 array_exchange(arr);
  35.         end
  36. };
复制代码
获取lua中的方法
  1. scriptEnv = LuaEnvExtension.Instance.NewTable();//在主lua环境中创建一个新的表作为当前脚本的环境
  2. LuaTable meta = LuaEnvExtension.Instance.NewTable();//创建一个新的表格存全局变量
  3. meta.Set("__index", LuaEnvExtension.Instance.Global);//获取全局变量作为元方法
  4. scriptEnv.SetMetaTable(meta);//设置meta为当前脚本的元表
  5. meta.Dispose();//回收meta
  6. LuaEnvExtension.Instance.DoString(luaText.text, "NoGCTest", scriptEnv);//拷贝lua脚本的方法到scriptEnv中
  7. scriptEnv.Set("self", this);//设置自身
  8. scriptEnv.Get("id", out f1);//获取泛型测试方法,我们并没有传给id方法参数,所以f1-f5都是空的
  9. scriptEnv.Get("id", out f2);
  10. scriptEnv.Get("id", out f3);
  11. scriptEnv.Get("id", out f4);
  12. scriptEnv.Get("id", out f5);
  13. scriptEnv.Get("array_exchange", out farr);//获取lua中的方法
  14. scriptEnv.Get("lua_access_csharp", out flua);
  15. scriptEnv.Get("exchanger", out ie);
  16. scriptEnv.Get("add", out add);
  17. scriptEnv.Set("g_int", 123);
  18. scriptEnv.Set(123, 456);
  19. int i;
  20. scriptEnv.Get("g_int", out i);
  21. scriptEnv.Get(123, out i);
复制代码
调用测试方法
  1. private void Update()
  2. {
  3.     //测试f1-f5方法
  4.     f1(1);
  5.     f2(new Vector3(1, 2, 3));
  6.     MyStruct mystruct1 = new MyStruct(5, 6);
  7.     f3(mystruct1);
  8.     f4(MyEnum.E1);
  9.     decimal dec1 = -32132143143100109.00010001010M;
  10.     f5(dec1);
  11.     add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult>是个方便调用的类型,可以自定义其他方法快捷调用
  12.                                      //测试a1-a5数据
  13.     farr(a1); //primitive value type array
  14.     farr(a2); //vector3 array
  15.     farr(a3); //custom struct array
  16.     farr(a4); //enum arry
  17.     farr(a5); //decimal arry
  18.     flua();//调用lua中的lua_access_csharp方法测试C#中的数据
  19.     ie.exchange(a2);//接口测试
  20.     scriptEnv.Set("g_int", 456);//调用lua数据测试
  21.     int i;
  22.     scriptEnv.Get("g_int", out i);
  23.     scriptEnv.Set(123.0001, mystruct1);
  24.     MyStruct mystruct2;
  25.     scriptEnv.Get(123.0001, out mystruct2);
  26.     decimal dec2 = 0.0000001M;
  27.     scriptEnv.Set((byte)12, dec1);
  28.     scriptEnv.Get((byte)12, out dec2);
  29.     int gdata = scriptEnv.Get<int>("GDATA");
  30.     scriptEnv.SetInPath("GDATA", gdata + 1);
  31.     int abc = scriptEnv.GetInPath<int>("A.B.C");
  32.     scriptEnv.SetInPath("A.B.C", abc + 1);
  33.     //检测是否满足gc回收条件
  34.     if (Time.time - LuaEnvExtension.lastGCTime > gcInterval)
  35.     {
  36.         LuaEnvExtension.Instance.GC();
  37.         LuaEnvExtension.lastGCTime = Time.time;
  38.     }
  39. }
复制代码
回收内存
  1. private void OnDestroy()
  2. {
  3.     //回收内存
  4.     f1 = null;
  5.     f2 = null;
  6.     f3 = null;
  7.     f4 = null;
  8.     f5 = null;
  9.     a1 = null;
  10.     a2 = null;
  11.     a3 = null;
  12.     a4 = null;
  13.     a5 = null;
  14.     farr = null;
  15.     flua = null;
  16.     ie = null;
  17.     add = null;
  18.     scriptEnv.Dispose();
  19. }
复制代码
完整代码

C#部分的代码
  1. using System;
  2. using UnityEngine;
  3. using XLua;
  4. #region test struct and method
  5. [GCOptimize]//只包含值类型的结构体,可以打GCOptimize标签,并生成代码,优化gc
  6. [LuaCallCSharp]//lua中使用C#,打标签生成代码做优化,否则会使用反射的方式访问,非常耗资源
  7.                //测试结构体
  8. public struct Pedding
  9. {
  10.     public byte c;
  11. }
  12. [GCOptimize]
  13. [LuaCallCSharp]
  14. //测试结构体
  15. public struct MyStruct
  16. {
  17.     public MyStruct(int p1, int p2)
  18.     {
  19.         a = p1;
  20.         b = p2;
  21.         c = p2;
  22.         e.c = (byte)p1;
  23.     }
  24.     public int a;
  25.     public int b;
  26.     public decimal c;
  27.     public Pedding e;
  28. }
  29. [LuaCallCSharp]
  30. //测试枚举
  31. public enum MyEnum
  32. {
  33.     E1,
  34.     E2
  35. }
  36. [CSharpCallLua]
  37. public delegate int IntParam(int p);//测试方法
  38. [CSharpCallLua]
  39. public delegate Vector3 Vector3Param(Vector3 p);//测试方法
  40. [CSharpCallLua]
  41. public delegate MyStruct CustomValueTypeParam(MyStruct p);//测试方法
  42. [CSharpCallLua]
  43. public delegate MyEnum EnumParam(MyEnum p);//测试方法
  44. [CSharpCallLua]
  45. public delegate decimal DecimalParam(decimal p);//测试方法
  46. [CSharpCallLua]
  47. public delegate void ArrayAccess(Array arr);//测试方法
  48. [CSharpCallLua]
  49. //测试接口
  50. public interface IExchanger
  51. {
  52.     void exchange(Array arr);
  53. }
  54. #endregion
  55. public class NoGCTest : MonoBehaviour
  56. {
  57.     private const float gcInterval = 1f;//gc回收间隔 1秒
  58.     public TextAsset luaText;//lua脚本
  59.     private LuaTable scriptEnv;//脚本的lua环境
  60.     #region test method params
  61.     IntParam f1;//测试方法
  62.     Vector3Param f2;
  63.     CustomValueTypeParam f3;
  64.     EnumParam f4;
  65.     DecimalParam f5;
  66.     ArrayAccess farr;
  67.     IExchanger ie;
  68.     Action flua;
  69.     LuaFunction add;
  70.     #endregion
  71.     #region test data
  72.     [NonSerialized]
  73.     public double[] a1 = new double[] { 1, 2 };//测试数据
  74.     [NonSerialized]
  75.     public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };
  76.     [NonSerialized]
  77.     public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };
  78.     [NonSerialized]
  79.     public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
  80.     [NonSerialized]
  81.     public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };
  82.     #endregion
  83.     #region test lua call c#
  84.     //lua中调用的测试方法
  85.     [LuaCallCSharp]
  86.     public float FloatParamMethod(float p)
  87.     {
  88.         return p;
  89.     }
  90.     [LuaCallCSharp]
  91.     public Vector3 Vector3ParamMethod(Vector3 p)
  92.     {
  93.         return p;
  94.     }
  95.     [LuaCallCSharp]
  96.     public MyStruct StructParamMethod(MyStruct p)
  97.     {
  98.         return p;
  99.     }
  100.     [LuaCallCSharp]
  101.     public MyEnum EnumParamMethod(MyEnum p)
  102.     {
  103.         return p;
  104.     }
  105.     [LuaCallCSharp]
  106.     public decimal DecimalParamMethod(decimal p)
  107.     {
  108.         return p;
  109.     }
  110.     #endregion
  111.     private void Awake()
  112.     {
  113.         scriptEnv = LuaEnvExtension.Instance.NewTable();//在主lua环境中创建一个新的表作为当前脚本的环境
  114.         LuaTable meta = LuaEnvExtension.Instance.NewTable();//创建一个新的表格存全局变量
  115.         meta.Set("__index", LuaEnvExtension.Instance.Global);//获取全局变量作为元方法
  116.         scriptEnv.SetMetaTable(meta);//设置meta为当前脚本的元表
  117.         meta.Dispose();//回收meta
  118.         LuaEnvExtension.Instance.DoString(luaText.text, "NoGCTest", scriptEnv);//拷贝lua脚本的方法到scriptEnv中
  119.         scriptEnv.Set("self", this);//设置自身
  120.         scriptEnv.Get("id", out f1);//获取泛型测试方法,我们并没有传给id方法参数,所以f1-f5都是空的
  121.         scriptEnv.Get("id", out f2);
  122.         scriptEnv.Get("id", out f3);
  123.         scriptEnv.Get("id", out f4);
  124.         scriptEnv.Get("id", out f5);
  125.         scriptEnv.Get("array_exchange", out farr);//获取lua中的方法
  126.         scriptEnv.Get("lua_access_csharp", out flua);
  127.         scriptEnv.Get("exchanger", out ie);
  128.         scriptEnv.Get("add", out add);
  129.         scriptEnv.Set("g_int", 123);
  130.         scriptEnv.Set(123, 456);
  131.         int i;
  132.         scriptEnv.Get("g_int", out i);
  133.         Debug.Log("g_int:" + i);
  134.         scriptEnv.Get(123, out i);
  135.         Debug.Log("123:" + i);
  136.     }
  137.     private void Update()
  138.     {
  139.         //测试f1-f5方法
  140.         f1(1);
  141.         f2(new Vector3(1, 2, 3));
  142.         MyStruct mystruct1 = new MyStruct(5, 6);
  143.         f3(mystruct1);
  144.         f4(MyEnum.E1);
  145.         decimal dec1 = -32132143143100109.00010001010M;
  146.         f5(dec1);
  147.         add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult>是个方便调用的类型,可以自定义其他方法快捷调用
  148.         //测试a1-a5数据
  149.         farr(a1); //primitive value type array
  150.         farr(a2); //vector3 array
  151.         farr(a3); //custom struct array
  152.         farr(a4); //enum arry
  153.         farr(a5); //decimal arry
  154.         flua();//调用lua中的lua_access_csharp方法测试C#中的数据
  155.         ie.exchange(a2);//接口测试
  156.         scriptEnv.Set("g_int", 456);//调用lua数据测试
  157.         int i;
  158.         scriptEnv.Get("g_int", out i);
  159.         scriptEnv.Set(123.0001, mystruct1);
  160.         MyStruct mystruct2;
  161.         scriptEnv.Get(123.0001, out mystruct2);
  162.         decimal dec2 = 0.0000001M;
  163.         scriptEnv.Set((byte)12, dec1);
  164.         scriptEnv.Get((byte)12, out dec2);
  165.         int gdata = scriptEnv.Get<int>("GDATA");
  166.         scriptEnv.SetInPath("GDATA", gdata + 1);
  167.         int abc = scriptEnv.GetInPath<int>("A.B.C");
  168.         scriptEnv.SetInPath("A.B.C", abc + 1);
  169.         //检测是否满足gc回收条件
  170.         if (Time.time - LuaEnvExtension.lastGCTime > gcInterval)
  171.         {
  172.             LuaEnvExtension.Instance.GC();
  173.             LuaEnvExtension.lastGCTime = Time.time;
  174.         }
  175.     }
  176.     private void OnDestroy()
  177.     {
  178.         //回收内存
  179.         f1 = null;
  180.         f2 = null;
  181.         f3 = null;
  182.         f4 = null;
  183.         f5 = null;
  184.         a1 = null;
  185.         a2 = null;
  186.         a3 = null;
  187.         a4 = null;
  188.         a5 = null;
  189.         farr = null;
  190.         flua = null;
  191.         ie = null;
  192.         add = null;
  193.         scriptEnv.Dispose();
  194.     }
  195. }
复制代码
lua部分的代码
  1. A = { B = { C = 789}};--定义一个结构体
  2. GDATA = 1234;--定义一个num类型
  3. local v3 = CS.UnityEngine.Vector3(7, 8, 9);--调用c#类中的参数
  4. local vt = CS.MyStruct(5, 6);--调用c#类中的参数
  5. --相当于泛型
  6. function id(...)
  7.         return ...;
  8. end
  9. --简单的相加方法
  10. function add(a, b)
  11.         return a + b ;
  12. end
  13. --数组index0 和 index1的交换
  14. function array_exchange(arr)
  15.         arr[0], arr[1] = arr[1], arr[0];
  16. end
  17. --测试访问C#中的方法
  18. function lua_access_csharp()
  19.         self:FloatParamMethod(123); --primitive
  20.         self:Vector3ParamMethod(v3); --vector3
  21.         local rnd = math.random(1, 100);
  22.         local r = self:Vector3ParamMethod({x = 1, y = 2, z = rnd}); --vector3
  23.         assert(r.x == 1 and r.y == 2 and r.z == rnd);
  24.         self:StructParamMethod(vt); --custom struct
  25.         r = self:StructParamMethod({a = 1, b = rnd, e = {c = rnd}});
  26.         assert(r.b == rnd and r.e.c == rnd);
  27.         self:EnumParamMethod(CS.MyEnum.E2); --enum
  28.         self:DecimalParamMethod(self.a5[0]);
  29.         self.a1[0], self.a1[1] = self.a1[1], self.a1[0]; -- field
  30. end
  31. --对应C#类中的IExchanger接口
  32. exchanger = {
  33.         exchange = function(self, arr)
  34.                 array_exchange(arr);
  35.         end
  36. };
复制代码
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 07:48 , Processed in 0.089934 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表