1. C# オブジェクトを Lua の userdata として扱う
デフォルトでは、C# のオブジェクトは Lua 側で userdata として表現され、実際のデータとメソッド呼び出しはすべて C# 側で処理されます。
function OperateVector3(vecA, vecB)
vecA.x = 10
print(type(vecA), vecA.x, vecA.y, vecA.z)
print("vecA:", vecA, "vecB:", vecB)
print("vecA + vecB:", vecA + vecB)
vecA:Set(vecA.x - vecB.x, vecA.y - vecB.y, vecA.z - vecB.z)
print(vecA)
print(CS.UnityEngine.Vector3.Normalize(vecA))
end
print("----メタテーブル変更前----")
OperateVector3(CS.UnityEngine.Vector3(1, 2, 3), CS.UnityEngine.Vector3(7, 8, 9))
xlua.genaccessor を用いた直接フィールドアクセス
xlua.genaccessor を使うことで、C# オブジェクトのフィールドに Lua 側から直接アクセス可能になります。これは、オフセットと型サイズを指定して、マネージドメモリ上の値を読み書きする低レベルな方法です。
local readX, writeX = xlua.genaccessor(0, 8) -- x フィールド: オフセット 0, float (8バイト)
local readY, writeY = xlua.genaccessor(4, 8) -- y フィールド: オフセット 4
local readZ, writeZ = xlua.genaccessor(8, 8) -- z フィールド: オフセット 8
local fieldReaders = {
x = readX, y = readY, z = readZ
}
local fieldWriters = {
x = writeX, y = writeY, z = writeZ
}
local instanceMethods = {
Set = function(obj, newX, newY, newZ)
print("Lua側 Vector3:Set 呼び出し")
writeX(obj, newX)
writeY(obj, newY)
writeZ(obj, newZ)
end
}
local vector3Meta = {
__index = function(obj, key)
if instanceMethods[key] then
return instanceMethods[key]
end
local reader = fieldReaders[key]
return reader and reader(obj)
end,
__newindex = function(obj, key, value)
local writer = fieldWriters[key]
if writer then
writer(obj, value)
else
error("未定義フィールド: " .. tostring(key))
end
end,
__tostring = function(obj)
return string.format("vector3 { %f, %f, %f }", obj.x, obj.y, obj.z)
end,
__add = function(a, b)
print("Lua側 Vector3 加算演算子")
return CS.UnityEngine.Vector3(a.x + b.x, a.y + b.y, a.z + b.z)
end
}
xlua.setmetatable(CS.UnityEngine.Vector3, vector3Meta)
print("----メタテーブル変更後----")
OperateVector3(CS.UnityEngine.Vector3(1, 2, 3), CS.UnityEngine.Vector3(7, 8, 9))
2. C# オブジェクトを Lua の table として再実装
別のアプローチとして、C# のクラスを完全に Lua 側のテーブルで置き換えることも可能です。これにより、コンストラクタや静的メソッド、インスタンスメソッドを Lua で自由に定義できます。
local LuaVector3Proto = {}
LuaVector3Proto.__index = LuaVector3Proto
function LuaVector3Proto:__tostring()
return string.format("struct { %d, %d, %d }", self.x, self.y, self.z)
end
function LuaVector3Proto:SwapXY()
self.x, self.y = self.y, self.x
end
-- インスタンス生成時のメタテーブル設定
xlua.setmetatable(CS.UnityEngine.Vector3, LuaVector3Proto)
-- クラス(静的)側の Lua 実装
local LuaVector3Class = {}
function LuaVector3Class.__call(_, x, y, z)
print("LuaVector3: コンストラクタ呼び出し")
local instance = { x = x, y = y, z = z }
setmetatable(instance, LuaVector3Proto)
return instance
end
setmetatable(LuaVector3Class, LuaVector3Class)
function LuaVector3Class.Print(target)
print("LuaVector3: Print", type(target), target)
end
-- C# の Vector3 クラス全体を Lua 実装に差し替え
xlua.setclass(CS.UnityEngine, "Vector3", LuaVector3Class)
-- 使用例
local v = CS.UnityEngine.Vector3(1, 2, 3)
print(type(v), v)
CS.UnityEngine.Vector3.Print(v)
v:SwapXY()
print(v)