CSToLua 特性

1.性能就不说。诞生的目的就是100%用lua写代码
使用lua版的 LookRotation 比c#的还要快,测试pc上快了一倍多。推测原因是: 1. luajit对数值计算提升很强。2. c# 四元数进行了跨语言调用。 如果可以直接注册c++对象,一定比c#跑的还快
2.可以扩展操作符函数到lua中.  包括为委托函数自定义了 +,- 操作符. 实际代码示例如下:
  local node = FindNode(self.transform, "BtnGo")
  local go = node.gameObject
  local ev = go:GetComponent(UIEventListener.GetClassType())
  local func = function() print("测试委托 + ") end
  ev.onClick = func
  local func = function() print("测试委托2 ") end
  ev.onClick = ev.onClick + func
3.更好的控制c#函数可见性, 对于废弃的函数,私有函数都不会导出。 也可以自己配置添加或者删除函数(比如给object对象加了Destroy函数。在u3d Destroy里面加了gc调用)
4.更快的回收内存, 一个Object.Destroy调用后就从c#端删除了对象。避免 gc 缓慢,交叉等等问题. 例如如下代码,在第三行调用要能把gameObject 为nil信息报出来。对于反射(甚至c#)无法实现这个特性
  因为 unity 延迟删除的特性,其实真的GameObject还没有删除,对于c# 这样写都不会报错。 而我们写逻辑其实希望这种问题能够提前暴露出来。
  local newGameObj = GameObject.New('NewObj')
  Object.Destroy(newGameObj) -- 这里也可以采用 newGameObject:Destroy() 方式调用,
  newGameObj:AddComponent(SkinnedMeshRenderer.GetClassType())
5. 可以支持数组参数。可以在lua端用table传递传递数组参数, 对可变参数列表采用原生支持,无需使用Table。
   可变参数例如 Debugger.Log(1,2,3) 
6. 处理二义性。如lua number参数类型可以对应很多c#函数,自动参数选取范围最大的函数。 比如System.Convert(65536) 不会把一个lua number 给匹配到 char 字符上去。
   对于lua 来说有 void Test(char a) 和 void Test(double a) 2个重载函数,只能把第二个注册给lua, 因为lua只有double。
7. 支持重载函数, 并且排序函数对于,相同参数个数, object 参数比较会放在后面,避免object可以匹配任意类型,对于可变参数数组会放在最后面。
    无论对于u3d还是其他第三方库,有通配类型object的不少。甚至既有 object 又有 object 的可变参数这样的重载函数组合
8. u3d类型为null检测. 对于已经为空的 unity object 进行提示。不包括lua主动传递的nil参数(确保当传递nil时,是自己确实想置null。)
  对于第几个参数以及参数类型进行错误提示,而不是针对整个函数提示,对于排错是十分有益的。工程中发现总是挡不住有人写很长的串式比如
  FindNode(self.transform, "Btn").gameObject:GetComponent(UIWidget.GetClassType()).  
  虽然可以编码规范来杜绝这种行为,更好的方式是即使出错也能直接提示到精确位置。对于单一函数调用,知道那个参数错误,对于排错速度也是大大有益的
  对于c#代码异常,如果是lua调用触发,会报出异常信息,这种出错信息可能会比较宽泛
9. 严格区分枚举类型和int值,避免造成某些u3d重载函数混淆. 比如 Transform:Rotate(vec, 0)
10. 支持导出模板类。可以作为自定义类型导出到lua中。


对于CSToLua为什么能跑快.  核心是减少了跨语言调用,关键如下:
1. 纯lua index, newindex 索引函数(后面为手机优化成了c版本,pc性能略降) 这个把transform.postion 读写从100+倍差距(与c#对比),拉入到了10以内(还是与c#对比),让属性调用飞起来。可谓核心发动机,游戏中的引擎。从这个可以看出80%的性能往往就是那几十行决定的。
2. 值类型的lua化,这个拉起了一倍左右,算不错的轮子吧(用lua重写了这些数学库)。减少了跨语言之间的调用。比如得到transform的position,rotation, cache下来再lua端对其进行计算,每帧只调用一次transform.position = pos. 再也不需要从transform 上获取 position信息了(前提是不能有其他c#代码修改位置和旋转,这样又节省了一半,一帧只有一个set调用了,呵呵,还可以从旋转上面直接取 transform.forward 信息, 是不是很棒), 这个也就几百行,还包括了一个函数的好几个版本对比。
(基本在14年底前完成了这些,值类型gc优化,由于协同,多state多线程问题过完年才提交,可见80%时间不在写核心代码上面。项目太忙偶尔才有时间给其打打补丁,包括最近还给值类型打打补丁,强迫症发作了,什么顺序求欧拉角度有区别么。。。。 还是矩阵直观啊,从u3d才开始大量用四元数, 总感觉不是那么顺手。)
有了这两个你也可以打造属于自己的alua, blua, nblua。是不是有点小心动呢

index 函数如下: 大体是从lua端找到变量名,如果是函数返回函数,对于属性则类型为table,table[1] 是get函数, table[2] 是set函数. 这与c++ tolua略有区别。它支持更复杂的特性。而在cstolua1.0 发布这个时候,无论在lua还是lua api 方面,笔者都还是个菜鸟。就搞了个简化版本。主要还要兼容luainterface metatable 方式。生成metatable名字要跟反射那边一直,这是个蛋疼的问题, 导致要做两个table. 一直想把两个table归一。(开始没想改动luainterface代码,后面还是越改越多)或许后面优化反射时候能够统一他们

对于newindex:  只需找到属性table,访问table[2]即可
第一个版本时候,自己造了一个 "_base" 字段放基类table,等lua熟悉了,才用metatable替换掉了

--index函数

local rawget = rawget
local rawset = rawset
local getmetatable = getmetatable
local type = type
local function index(obj,name)
  local meta = getmetatable(obj)
  local parent = meta
  local v = nil

  while meta~= nil do
    v = rawget(meta, name)

    if v~= nil then
      if parent ~= meta then rawset(parent, name, v) end
      local t = type(v)

      if t == 'function' then
        return v
      elseif t == 'table' then
        local func = v[1]

        if func ~= nil then
          return func(obj, name)
        end
      end
      break
    end

    meta = getmetatable(meta)  --查找基类metatabl
  end

 

  error('unknown member name '..name, 2)
  return nil
end

 
--newindex 函数

local rawget = rawget
local getmetatable = getmetatable
local rawset = rawset

local function newindex(obj, name, val)
  local meta = getmetatable(obj)
  local parent = meta
  local v = nil

  while meta~= nil do
    v = rawget(meta, name)

    if v~= nil then
      if parent ~= meta then rawset(parent, name, v) end
      local func = v[2]
      if func ~= nil then
        return func(obj, name, val)
      end
      break
    end

    meta = getmetatable(meta)
end

  error('field or property '..name..' does not exist', 2)
  return nil
end


对于 Vector3.lua 之类就不贴了,开源的引擎代码一大堆,自己转一个就行。你是喜欢Cry呢,还是Unreal 呢,还是这个渣画面的U3D呢。 当然你也可以直接拷贝一个cstolua里面的

posted on 2015-06-06 00:21  阿蒙1024  阅读(933)  评论(0)    收藏  举报

导航