版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/NippyLi/article/details/79406890
- 避免值类型的GC
一个C#纯值类型(注:指的是一个只包含值类型的struct,可以嵌套其它只包含值类型的struct)或者C#枚举值加上了这个配置。xLua会为该类型生成gc优化代码,效果是该值类型在lua和c#间传递不产生(C#)gc alloc,该类型的数组访问也不产生gc
除枚举之外,包含无参构造函数的复杂类型,都会生成lua table到该类型,以及改类型的一维数组的转换代码,这将会优化这个转换的性能,包括更少的gc alloc。
using UnityEngine;
using System;
using XLua;
namespace XLuaTest
{
//一个C#纯值类型(注:指的是一个只包含值类型的struct,可以嵌套其它只包含值类型的struct)或者C#枚举值加上了这个配置。
//xLua会为该类型生成gc优化代码,效果是该值类型在lua和c#间传递不产生(C#)gc alloc,该类型的数组访问也不产生gc
[GCOptimize]
[LuaCallCSharp]
public struct Pedding
{
public byte c;
}
[GCOptimize]
[LuaCallCSharp] //lua调用c#
public struct MyStruct
{
public MyStruct(int p1, int p2)
{
a = p1;
b = p2;
c = p2;
e.c = (byte)p1;
}
public int a;
public int b;
public decimal c;
public Pedding e;
}
[LuaCallCSharp]
public enum MyEnum
{
E1,
E2
}
///c#调用lua
[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);
}
[LuaCallCSharp]
public class NoGc : MonoBehaviour
{
//lua虚拟机,建议全局唯一
LuaEnv luaenv = new LuaEnv();
//委托用来调用lua方法
IntParam f1;
Vector3Param f2;
CustomValueTypeParam f3;
EnumParam f4;
DecimalParam f5;
ArrayAccess farr;
Action flua;
//接口用来映射lua里的table
IExchanger ie;
//映射lua方法 LuaFunction上有个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回
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 };
public float FloatParamMethod(float p)
{
return p;
}
public Vector3 Vector3ParamMethod(Vector3 p)
{
return p;
}
public MyStruct StructParamMethod(MyStruct p)
{
return p;
}
public MyEnum EnumParamMethod(MyEnum p)
{
return p;
}
public decimal DecimalParamMethod(decimal p)
{
return p;
}
// Use this for initialization
void Start()
{
luaenv.DoString(@"
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
--获取一个vector3对象
local v3 = CS.UnityEngine.Vector3(7, 8, 9)
--获取XLuaTest空间下的MyStruct结构体
local vt = CS.XLuaTest.MyStruct(5, 6)
--访问c#,加了[LuaCallCSharp]特性
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脚本
luaenv.Global.Set("monoBehaviour", this);
//获取lua中的全局方法映射到delegate中
luaenv.Global.Get("id", out f1);
//f1 = luaenv.Global.Get<IntParam>("id");
luaenv.Global.Get("id", out f2);
// f2 = luaenv.Global.Get<Vector3Param>("id");
luaenv.Global.Get("id", out f3);
// f3 = luaenv.Global.Get<CustomValueTypeParam>("id");
luaenv.Global.Get("id", out f4);
// f4 = luaenv.Global.Get<EnumParam>("id");
luaenv.Global.Get("id", out f5);
//f5 = luaenv.Global.Get<DecimalParam>("id");
luaenv.Global.Get("array_exchange", out farr);
//farr = luaenv.Global.Get<ArrayAccess>("array_exchange");
luaenv.Global.Get("lua_access_csharp", out flua);
//flua = luaenv.Global.Get<Action>("lua_access_csharp");
luaenv.Global.Get("add", out add);
//add = luaenv.Global.Get<LuaFunction>("add");
//映射table到接口
luaenv.Global.Get("exchanger", out ie);
//ie = luaenv.Global.Get<IExchanger>("exchanger");
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);
}
//值类型之间为产生GC
void Update()
{
// c# call lua function with value type but no gc (using delegate)
f1(1); // primitive type
Vector3 v3 = new Vector3(1, 2, 3); // vector3
f2(v3);
MyStruct mystruct = new MyStruct(5, 6); // custom complex value type
f3(mystruct);
f4(MyEnum.E1); //enum
decimal d = -32132143143100109.00010001010M;
decimal dr = f5(d);
System.Diagnostics.Debug.Assert(d == dr);
// using LuaFunction.Func<T1, T2, TResult>
System.Diagnostics.Debug.Assert(add.Func<int, int, int>(34, 56) == (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
flua();
//c# call lua using interface
ie.exchange(a2);
//no gc LuaTable use
luaenv.Global.Set("g_int", 456);
int i;
luaenv.Global.Get("g_int", out i);
System.Diagnostics.Debug.Assert(i == 456);
luaenv.Global.Set(123.0001, mystruct);
MyStruct mystruct2;
luaenv.Global.Get(123.0001, out mystruct2);
System.Diagnostics.Debug.Assert(mystruct2.b == mystruct.b);
decimal dr2 = 0.0000001M;
luaenv.Global.Set((byte)12, d);
luaenv.Global.Get((byte)12, out dr2);
System.Diagnostics.Debug.Assert(d == dr2);
int gdata = luaenv.Global.Get<int>("GDATA");
luaenv.Global.SetInPath("GDATA", gdata + 1);
//gdata = luaenv.Global.Get<int>("GDATA");
//Debug.Log(gdata);
System.Diagnostics.Debug.Assert(luaenv.Global.Get<int>("GDATA") == gdata + 1);
int abc = luaenv.Global.GetInPath<int>("A.B.C"); //789
luaenv.Global.SetInPath("A.B.C", abc + 1);
//Debug.Log(luaenv.Global.GetInPath<int>("A.B.C"));
System.Diagnostics.Debug.Assert(luaenv.Global.GetInPath<int>("A.B.C") == abc + 1);
//清除Lua的未手动释放的LuaBase(比如,LuaTable, LuaFunction),以及其它一些事情。
luaenv.Tick();
}
void OnDestroy()
{
f1 = null;
f2 = null;
f3 = null;
f4 = null;
f5 = null;
farr = null;
flua = null;
ie = null;
add = null;
luaenv.Dispose();
}
}
}