Как скрипт может сохранить свои значения при загрузке разных скриптов в Lua? - PullRequest
1 голос
/ 01 марта 2010

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

1) Вызов dofile в конструкторе противника, а затем вызов его функции сценария в его функции Update, что происходит в каждом игровом цикле. Проблема в том, что Lua просто использует скрипт последнего созданного врага, поэтому все враги используют один и тот же скрипт в функции Update. Таким образом, объект, который я описал выше, который не использует тот же сценарий для своего A.I. использует скрипт других врагов.

2) Вызов dofile в функции Update и последующий вызов функции скрипта сразу после нее. Проблема в том, что dofile вызывается в функции обновления каждого объекта, поэтому после запуска функции AILogic и обновления данных для этого скрипта все это просто сбрасывается, когда dofile снова вызывается для другого врага. Мой самый большой вопрос здесь заключается в том, есть ли какой-нибудь способ сохранить значения в сценарии, даже когда я переключаюсь на запуск другого.

Я читал о функциональных средах в Lua, но я не совсем уверен, как правильно их реализовать. Это правильное направление? Любой совет приветствуется, спасибо.

Редактировать: я также подумал о создании отдельного места для хранения этих данных, вместо того чтобы делать это в скрипте Lua.

Edit2: добавлен пример кода. (Просто тест, чтобы функциональность заработала).

-- Slime's Script

local count = 0;

function AILogic( Slime )
  --Make the slime move in circles(err a square)
  if count < 4 then
    Slime:MoveDir( 0 );
  elseif count < 8 then
    Slime:MoveDir( 2 );
  elseif count < 12 then
    Slime:MoveDir( 1 );
  elseif count < 16 then
    Slime:MoveDir( 3 );
  else
    count = 0;
  end
  count = count + 1;
end

Ответы [ 2 ]

1 голос
/ 01 марта 2010

Интерпретатор lua запускает каждую строку как свой собственный фрагмент, что означает, что у локальных пользователей есть область видимости строки, поэтому пример кода не может быть запущен как есть. Либо нужно запустить все сразу (без разрывов строк), без локальных операторов, либо запустить в блоке do ... end.

Что касается вопроса в ОП. Если вы хотите использовать одну и ту же функцию (это та же функция во время выполнения), функция должна принимать данные в качестве аргументов. Однако, если вы в порядке использования того же кода, но разных (во время выполнения) функций, чем вы можете использовать замыкания для хранения локальных / отдельных данных.

local function make_counter()
    local count = 0

    return function ()
        local c = count
        count = count + 1
        return c
    end
end

c1 = make_counter()
c2 = make_counter()
c3 = make_counter()

print(c1())
print(c1())
print(c1())
print(c1())
print(c2())
print(c3())
print(c2())
print(c3())
print(c2())
print(c3())

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

1 голос
/ 01 марта 2010

Канонической ссылкой для этого является текст ссылки . Объясняя это кратко, мы отработаем следующий код с сайта:

a = 1
local newgt = {}        -- create new environment
setmetatable(newgt, {__index = _G})
setfenv(1, newgt)    -- set it

Первая строка устанавливает (глобальную) переменную "a". Вы можете просмотреть это как настройку значений по умолчанию для вашего кода. (Имейте в виду, что в Lua все переменные являются глобальными, если вы не объявите их с помощью "local".)

Следующая строка создает таблицу, которая будет вашей новой средой. Он является локальным по отношению к функции / чанку, в которых вы выполняете, поэтому он не будет сброшен чем-либо еще, работающим сейчас или позже.

Третья строка - это начало магии. Чтобы понять это, вам нужно понять метаметоды В сущности, однако, вы используете метамагия Lua, чтобы гарантировать, что любые глобальные имена, которые не определены в вашей будущей функциональной среде, получат решен в контексте вашей старой глобальной среды. По сути, это означает, что если вы используете имя, которого нет в вашей функциональной среде, Lua будет автоматически охотиться в глобальной среде, в которой вы привыкли находить имя. (Одним словом: наследство.)

Четвертая строка - это то, где вы получаете то, что ищете. Setfenv (1, ...) означает, что это меняет среду для вашей текущей функции. (Вы можете использовать 2 для вызывающей функции, 3 для вызывающей функции и т. Д. На линии вверх.) Второй параметр - это таблица, которую вы только что создали, дополненная наследованием старого поведения. Ваша функция теперь выполняется в новой глобальной среде. В нем есть все имена и значения старой среды (в том числе функции и глобальная переменная «a», которую вы вводите). Однако, если вы ЗАПИШИТЕ имя, оно не будет перезаписывать глобальное состояние. Он перезапишет вашу локальную копию.

Рассмотрим следующий код:

a = 10
b = 20

То, что вы сделали сейчас, заставило вашу таблицу окружения функций выглядеть следующим образом:

{a = 10, b=20}

Ваша «глобальная» среда, короче говоря, содержит только две переменные: a (значение 10) и b (значение 20). Когда вы откроете «a» позже, вы получите локальную копию с 10 - старое глобальное значение, хранящееся в вашем метатабле, теперь затенено и по-прежнему установлено на 1 - а если вы откроете «b», вы получите 20, несмотря на то, что исходное глобальное состояние, вероятно, даже не имеет переменной "b" для доступа И вы все равно сможете получить доступ ко всем функциям и т. Д., Которые вы определили до этого момента.


Отредактировано для добавления тестового кода для устранения проблемы OP.

Я поместил следующий код в "junk.lua":

a = 1
local newgt = {}
setmetatable(newgt, {__index = _G})
setfenv(1, newgt)
print(a)
a = 10
print(a)
print(newgt)

Вывод будет следующим:

$ lua junk.lua
1
10
table: 0x976d040

Используется Lua 5.1.4. Какой вывод вы видите?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...