展示了Lua继承Unity中的Transform类——新建的LuaTransform类。
「1」代码
操作代码如下:
LuaTransform =
{
}
function LuaTransform.Extend(u)
local t = {}
local _position = u.position
tolua.setpeer(u, t)
t.__index = t
local get = tolua.initget(t)
local set = tolua.initset(t)
local _base = u.base
--重写同名属性获取
get.position = function(self)
return _position
end
--重写同名属性设置
set.position = function(self, v)
if _position ~= v then
_position = v
_base.position = v
end
end
--重写同名函数
function t:Translate(...)
print('child Translate')
_base:Translate(...)
end
return u
end
--既保证支持继承函数,又支持go.transform == transform 这样的比较
function Test(node)
local v = Vector3.one
local transform = LuaTransform.Extend(node)
local t = os.clock()
for i = 1, 200000 do
transform.position = transform.position
end
print('LuaTransform get set cost', os.clock() - t)
transform:Translate(1,1,1)
local child = transform:Find('child')
print('child is: ', tostring(child))
if child.parent == transform then
print('LuaTransform compare to userdata transform is ok')
end
transform.xyz = 123
transform.xyz = 456
print('extern field xyz is: '.. transform.xyz)
end
c#代码如下:
new LuaResLoader();
lua = new LuaState();
lua.Start();
LuaBinder.Bind(lua);
lua.DoString(script, "TestInherit.cs");
float time = Time.realtimeSinceStartup;
for (int i = 0; i < 200000; i++)
{
Vector3 v = transform.position;
transform.position = v;
}
time = Time.realtimeSinceStartup - time;
Debugger.Log("c# Transform get set cost time: " + time);
lua.Call("Test", transform, true);
lua.Dispose();
lua = null;
「2」需要了解的部分
- 首先创建空表LuaTransform,LuaTransform.Extend(u)方法用于重写同名属性的get和set,还可以重写同名函数,最后return u。
- 那么如何写这个Extend方法呢?首先参数和返回值都是u,相当于创建了u的peer表t,在t里加东西:
local t = {}
local _position = u.position
tolua.setpeer(u, t)
t.__index = t
local get = tolua.initget(t)
local set = tolua.initset(t)
local _base = u.base
tolua.setpeer(cs_obj,lua_table)
将lua_table设置为cs_obj的peer表。此后,在对应c++_obj进行访问的时候,会先去peer表中查询,然后再去对应的metatable中查询。
tolua.setpeerr(csobj, peer)
设置csobj的peer表
csobj: C#对象在lua中对应的userdata
peer: 一个lua table
_base = u.base
,理解为base就是原来的还没改动过的那个u,方法,属性都是原来的。
这样,在重写方法的时候,我们可以先让其执行原来的步骤,再加新语句:
--重写同名函数
function t:Translate(...)
print('child Translate')
_base:Translate(...)
end
那这样做有什么好处呢?
好处就在于速度提升了很多,每次找transform不必去找node的position,而是自己的_position,岂不美哉。
看一下速度对比:
t = os.clock()
for i = 1, 200000 do
node.position = node.position
end
print('No use LuaTransform get set cost', os.clock() - t)
local transform = LuaTransform.Extend(node)
local t = os.clock()
for i = 1, 200000 do
transform.position = transform.position
end
print('LuaTransform get set cost', os.clock() - t)
速度对比
在没有扩展之前,当我们访问或设置userdata不存在的成员的时候,程序就会出错,但是在扩展之后,我们便可以扩展对象的成员。
访问和设置position的时候就会调用到get.position和set.position。
function t:AddComponentIfNil(comp)
if nil == _base:GetComponent(t) then
_base:AddComponent(comp)
end
end
我们还可以修改GameObject的同名方法,例如我们可以将上面的AddComponentIfNil修改为AddComponent。
参考了Unity3D开发小贴士(七)Lua里扩展C#对象
网友评论