LUA:避免通过引用传递
LUA: Avoiding passing by reference
我刚刚开始学习 LUA,我遇到了一个问题,我不确定 "properly" 可以用哪种方式解决。
当我将 Defold vmath.vector3
传递给我的函数时,它似乎是通过引用传递的,因此被更改了。
但是,如果我将它乘以任何值,问题就解决了。
还有另一种更正确的方法来解决这个问题吗?我不想修改作为参数传递的原始向量。
function M.get_nearest_tile(x, y)
if y then -- if we've got 2 inputs, use x & y
x = math.floor(x / M.TILE_SIZE)
y = math.floor(y / M.TILE_SIZE)
return x, y
else -- if we've only got 1 input, use as vector
local vec = x * 1 -- multiplying by 1 to avoid modifying the real vector
vec.x = math.floor(vec.x / M.TILE_SIZE)
vec.y = math.floor(vec.y / M.TILE_SIZE)
return vec.x, vec.y
end
end
您的 else
分支中已有解决方案:您必须先创建向量的副本,然后再对其应用 "modifying" 操作。
就其他选项而言,也许可以想出一种使用代理表的方法,但这将比仅创建一个副本复杂得多。
由于您将 x
和 y
作为两个值返回,因此您可以在不修改任何表的情况下以相同的方式实现两个分支:
function M.get_nearest_tile(x, y)
local newX, newY
if y then -- if we've got 2 inputs, use x & y
newX = math.floor(x / M.TILE_SIZE)
newY = math.floor(y / M.TILE_SIZE)
else -- if we've only got 1 input, use as vector
newX = math.floor(x.x / M.TILE_SIZE)
newY = math.floor(x.y / M.TILE_SIZE)
end
return newX, newY
end
Defold 提供了一些在游戏开发中非常有用的特殊数据结构:
- vector3 - vmath.vector3(x,y,z),用于描述 3D 坐标系中的位置或方向
- vector4 - vmath.vector4(x,y,z,w),用于颜色、色调等(红色、绿色、蓝色、alpha)
- quat - vmath.quat() 描述旋转的四元数
- matrix4 - vmath.matrix4() 一个 4x4 值矩阵。对于视图和投影矩阵等非常有用
Defold 游戏引擎使用以上所有内容,但您会在其他游戏引擎中找到相同类型的数据结构。
上面的数据结构有一个共同点:它们都是Lua类型userdata
print(type(vmath.vector3())) -- "userdata"
用户数据始终通过引用传递,这就是您看到所描述行为的原因。 Defold 确实提供了制作副本的方法:
local copy = vmath.vector3(original) -- copy the vector3 'original'
local copy = vmath.vector4(original) -- copy the vector4 'original'
local copy = vmath.quat(original) -- copy the quaternion 'original'
local copy = vmath.matrix4(original) -- copy the matrix4 'original'
我刚刚开始学习 LUA,我遇到了一个问题,我不确定 "properly" 可以用哪种方式解决。
当我将 Defold vmath.vector3
传递给我的函数时,它似乎是通过引用传递的,因此被更改了。
但是,如果我将它乘以任何值,问题就解决了。
还有另一种更正确的方法来解决这个问题吗?我不想修改作为参数传递的原始向量。
function M.get_nearest_tile(x, y)
if y then -- if we've got 2 inputs, use x & y
x = math.floor(x / M.TILE_SIZE)
y = math.floor(y / M.TILE_SIZE)
return x, y
else -- if we've only got 1 input, use as vector
local vec = x * 1 -- multiplying by 1 to avoid modifying the real vector
vec.x = math.floor(vec.x / M.TILE_SIZE)
vec.y = math.floor(vec.y / M.TILE_SIZE)
return vec.x, vec.y
end
end
您的 else
分支中已有解决方案:您必须先创建向量的副本,然后再对其应用 "modifying" 操作。
就其他选项而言,也许可以想出一种使用代理表的方法,但这将比仅创建一个副本复杂得多。
由于您将 x
和 y
作为两个值返回,因此您可以在不修改任何表的情况下以相同的方式实现两个分支:
function M.get_nearest_tile(x, y)
local newX, newY
if y then -- if we've got 2 inputs, use x & y
newX = math.floor(x / M.TILE_SIZE)
newY = math.floor(y / M.TILE_SIZE)
else -- if we've only got 1 input, use as vector
newX = math.floor(x.x / M.TILE_SIZE)
newY = math.floor(x.y / M.TILE_SIZE)
end
return newX, newY
end
Defold 提供了一些在游戏开发中非常有用的特殊数据结构:
- vector3 - vmath.vector3(x,y,z),用于描述 3D 坐标系中的位置或方向
- vector4 - vmath.vector4(x,y,z,w),用于颜色、色调等(红色、绿色、蓝色、alpha)
- quat - vmath.quat() 描述旋转的四元数
- matrix4 - vmath.matrix4() 一个 4x4 值矩阵。对于视图和投影矩阵等非常有用
Defold 游戏引擎使用以上所有内容,但您会在其他游戏引擎中找到相同类型的数据结构。
上面的数据结构有一个共同点:它们都是Lua类型userdata
print(type(vmath.vector3())) -- "userdata"
用户数据始终通过引用传递,这就是您看到所描述行为的原因。 Defold 确实提供了制作副本的方法:
local copy = vmath.vector3(original) -- copy the vector3 'original'
local copy = vmath.vector4(original) -- copy the vector4 'original'
local copy = vmath.quat(original) -- copy the quaternion 'original'
local copy = vmath.matrix4(original) -- copy the matrix4 'original'