LUA: избегать прохождения по ссылке

Я только начинаю изучать LUA, и у меня есть проблема, которую я не уверен, какой способ "правильно" решить. Когда я прохожу дефолд 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

3 ответа

Решение

Так как ты возвращаешься 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), полезный для описания позиций или направления в трехмерной системе координат
  • vector4 - vmath.vector4(x,y,z,w), используется для цвета, оттенка и т. д. (красный, зеленый, синий, альфа)
  • 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'

У вас уже есть решение в вашем else ветвь: вам придется создать копию ваших векторов, прежде чем применять к ним "модифицирующие" операции.

Что касается других опций, может быть возможно придумать способ использования прокси-таблиц, но это будет намного сложнее, чем просто создание копии.

Другие вопросы по тегам