LUA: избегайте передачи по ссылке

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

Откуда взялся vector3? Это Роблокс или что-то в этом роде?

Henri Menke 13.11.2018 23:15

Ах, извините, я чувствую себя глупо. Я думал, что это из математики. Это от "vmath", который используется Defold (игровой движок).

Ghork 13.11.2018 23:18

Согласно документам, вы можете скопировать вектор с помощью local new = vmath.vector3(old)defold.com/ref/vmath/#vmath.vector3:v1

Henri Menke 13.11.2018 23:19

Вау ... Я действительно обманул себя на этот раз ... Я думал, что у меня, вероятно, будет такая же проблема с таблицей, поэтому я сказал себе, что это проблема с LUA в целом, и не стал проверять их документы ... , Я думаю, это настоящий ответ, хотя то, что я спрашивал, было неправильным с самого начала. Мне нужно попробовать, что произойдет, если я сделаю то же самое со столом.

Ghork 13.11.2018 23:24

Что касается вашего исходного вопроса, вы не можете «выключить» передачу по ссылке. Если что-то реализовано как ссылочный тип, оно будет передано как таковое. Копирование таблиц в Lua нетривиально, потому что это действительно зависит от того, как и какую часть содержимого вы хотите скопировать (рекурсивный, метатаблицы и т. д.).

Henri Menke 13.11.2018 23:30

Понятно, спасибо вам большое за объяснение!

Ghork 13.11.2018 23:40

Нитпик: Это Lua, а не LUA.

britzl 14.11.2018 06:04

Вы получите такой же результат при прохождении стола. Как упоминал выше Генри Менке, скопировать таблицу Lua нетривиально.

britzl 14.11.2018 06:05
Что такое компоненты React? Введение в компоненты | Типы компонентов
Что такое компоненты React? Введение в компоненты | Типы компонентов
Компонент - это независимый, многократно используемый фрагмент кода, который делит пользовательский интерфейс на более мелкие части. Например, если мы...
1
8
138
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

Ответ принят как подходящий

Поскольку вы возвращаете 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

У вас есть повторяющееся объявление x и y, хотя синтаксически оно не неверно, оно не будет работать должным образом.

dualed 14.11.2018 01:05

@dualed: Понял. Фиксированный.

luther 14.11.2018 01:27

Я искал очевидное решение, не связанное с Defold.

Ghork 14.11.2018 10:27

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'

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