Unity中xLua与toLua对Vector3的优化

目录

  1. 概述
    1.1 Vector3的定义
    1.2 主要优化的是什么?
  2. xLua对Vector3的优化
    2.1 xLua创建Vector3
    2.2 xLua获取Vector3 -- C#的Vector3传入lua
    2.3 xLua 设置 Vector3到C#
    2.4 GCOptimize -- PushUnityEngineVector3的由来
  3. toLua对Vector3的优化
    3.1 toLua创建Vector3
    3.2 toLua获取Vector3 -- C#的Vector3传入lua
    3.3 toLua 设置 Vector3到C#
  4. xLua与toLua对Vector3的优化的区别
    4.1 效率性能的比较
    4.2 扩展性的比较

一. 概述

1.1 Vector3的定义

public struct Vector3,是一个struct 结构体,值类型。

1.2 主要优化的是什么?

主要优化 减少gc + 减少lua与C#的交互。

  1. 为什么会产生gc?
    原因是boxing(装箱)和unboxing(拆箱)。Vector3(栈)转为object类型需要boxing(堆内存中),object转回Vector3需要unboxing,使用后释放该object引用,这个堆内存被gc检测到已经没引用,释放该堆内存,产生一个gc内存。

  2. 如何优化gc?
    值拷贝

二. xLua对Vector3的优化

2.1 xLua创建Vector3

lua中有2种方式可以表示Vector3:

  1. 创建Vector3对象,使用userdata:CS.UnityEngine.Vector3(7, 8, 9)
    1. 调用UnityEngineVector3Wrap中函数 static int __CreateInstance(RealStatePtr L)

    2. C#中new一个Vector3: UnityEngine.Vector3 __cl_gen_ret = new UnityEngine.Vector3(x, y, z);

    3. translator.PushUnityEngineVector3(L, __cl_gen_ret);
      要注意的是push方法是PushUnityEngineVector3,普通是translator.Push

      xlua push vec3 to lua 2.png

    4. PushUnityEngineVector3做的优化是申请一块userdata(size=12),将Vector3拆成3个float,Pack到userdata,push到lua

      xlua push float3 to lua 3.png

    5. 这种Vector3 userdata传给C#后,有一个与Pack对应的UnPack 过程。

  2. Table替代 : {x = 1, y = 2, z = 3}
    • 创建时,不与Unity C#交互(这与toLua类似)
    • 传给C#后,在C# UnPack 这个table,取出x、y、z, 赋值给new Vector3使用。 UnPack 在2.3中说明。

2.2 xLua获取Vector3 -- C#的Vector3传入lua

lua中 aTransform.position获取Vector3坐标:

  1. UnityEngineTransformWrap. _g_get_position lua想从transform获取position
transform getposition.png
  1. 获取C# transform对象:UnityEngine.Transform __cl_gen_to_be_invoked = (UnityEngine.Transform)translator.FastGetCSObj(L, 1);
  2. translator.PushUnityEngineVector3(L, __cl_gen_to_be_invoked.position); 这和2.1中创建一个Vector3 push userdata到lua过程一致。

2.3 xLua 设置 Vector3到C#

lua中 aTransform.position = Vector3坐标:

  1. UnityEngineTransformWrap. _s_set_position, lua想把pos设置到transform.position

    xLua transform setposition.png

  2. 设置position有2.1中的2种方式:

    1. 创建Vector3对象: aTransform.position = CS.UnityEngine.Vector3(7, 8, 9)

      先获取userdata指针,再调用 CopyByValue.UnPack从指向内存的起始地址读取x,y,z值,设置到out UnityEngine.Vector3 field

    2. Table替代 : aTransform.position = {x = 1, y = 2, z = 3}
      直接调用 CopyByValue.UnPack,将Table的x,y,z值取出,设置到out UnityEngine.Vector3 val

transform setposition get.png
  1. CopyByValue.UnPack
    上面2种方式调用的 CopyByValue.UnPack实现不同;
    1. userdata的方式,Pack的时候,使用xlua_pack_float3,对应的UnPack过程使用xlua_unpack_float3,解出userdata struct.
      xlua userdata方式设置vector3.png
    2. lua table,从栈中依次读取3个float值。


      xlua table方式设置vector3.png

2.4 GCOptimize -- PushUnityEngineVector3的由来

  1. 为何Vector3的push到lua 会有一个针对优化的接口PushUnityEngineVector3
    Vector3 struct配置了GCOptimize属性(对于常用的UnityEngine的几个struct,Vector系列,Quaternion,Color。。。均已经配置了该属性),这个属性可以通过配置文件或者C# Attribute实现;

    GCOptimize Vector3.png

  2. 从GCOptimize列表中去掉Vector3 会怎么样呢?
    PushUnityEngineVector3接口就不存在了,而Vector3的push到lua会使用translator.Push(L, __cl_gen_ret); ,不做优化public void Push(RealStatePtr L, object o),会产生boxing(装箱)和unboxing(拆箱),代表着一个gc。

    去掉vector3的GCOptimize后的push.png


三. toLua对Vector3的优化

toLua用lua重新实现了Vector3,包含所有方法;文件地址:tolua-master\Assets\ToLua\Lua\UnityEngine\Vector3.lua

3.1 toLua创建Vector3

Vector3.New(x, y, z)

toLua并没有跟Unity C#交互.

3.2 toLua获取Vector3 -- C#的Vector3传入lua

lua中 aTransform.position获取Vector3坐标:

  1. C# UnityEngine_TransformWrap.get_position;调用ToLua.Push

    toLua get_position.png

  2. C#传入Vector3的x,y,z;


    toLua get_position pushvec3.png
  3. 在lua建一个lua table,把x,y,z设置为对应字段;

  4. 设置该table的metatable为Vector3.lua的方法实现;

3.3 toLua 设置 Vector3到C#

  1. 从栈中取出对应table的x,y,z字段


    toLua set_position ToVector3.png
  2. C# new一个Vector3,将x,y,z赋值到Vector3;
    与xLua的table替代方式非常类似。

四. xLua与toLua对Vector3的优化的区别

  1. 效率性能的比较,toLua高
    1. xLua与toLua都不产生gc
    2. xLua在创建Vector3的userdata方式和Vector3的方法调用,都需要跟Unity C#交互;而toLua在这两方面是纯Lua端执行,无需跟Unity C#交互,效率最高。
    3. xLua有一个特点:所有无GC的类型,它的数组访问也没有GC。
  2. 扩展性的比较,xLua高
    toLua重新Lua实现的类,需要增加一种新的值类型十分困难, 数量有限,并且与Unity C# Vector3核心代码深度耦合。
toLua lua类列表.png

xLua支持的struct类型宽泛的多,包含枚举,用户要做的事情也很简单,用GCOptimize声明一下类型即可。支持自定义struct。(struct要求1.含无参构造函数 2.只包含值类型,可以嵌套其它只包含值类型的struct)

相关链接

  1. xlua github
  2. xlua特性
  3. tolua 官网
  4. tolua github
  5. Unity下XLua方案的各值类型GC优化深度剖析
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容