Пятница, 24.01.2025, 07:25
| RSS
F.O.R.U.M.
Главная | Вылеты. Их причины и способы борьбы - Форум
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Вылеты. Их причины и способы борьбы
frontДата: Понедельник, 12.10.2009, 16:38 | Сообщение # 1
Admin
Группа: Администраторы
Сообщений: 152
Репутация: 229
Статус: Оффлайн
Все мы знаем, что движок ведёт себя, как капризная невеста, и вылетает от малейшего чиха.
"Причины вылетов:"
1. Синтаксические ошибки в коде. Как правило, лог при этом содержит что-то вроде
Код
attempt to index global '<имя файла>' (a nil value)т.е. движку не удалось скомпилить модуль и его значение (модуля) равно нулю

2. Ошибки времени выполнения Lua. Лог обычно содержит указание ошибки модуль и строку, в которой ошибка произошла. Типа такого:
Код
LUA error: ....k.e.r. 1.0004\gamedata\scripts\<имя файла>.script:<номер строки>: attempt to index global 'npc' (a nil value)К типичным ошибка относятся попытки вызвать несуществующий метод класса (и вообще индексировать что-бы то ни было несуществующим ключом) или, к примеру, конкатенация строки с nil.

3. Ошибки времени выполнения самого игрового движка. Лога обычно нет, т.е. движок тихо слетает, сам в лог ничего не пишет, а забуферизированный до этого момента лог теряется. Иногда, правда, что-то в логе есть, но бывает это весьма редко. Ошибки движка вызваны неправильным использованием функций самого движка. Например, попытка заспавнить объект с несуществующей секцией.
Кроме того скрипты выполняются с прекомпиляцией, поэтому для запуска изменённого скрипта надо как минимум перегрузить сохранёнку. Кстати, для справки. в отличие от скриптов файлы конфигураций подгружаются уже при старте программы ещё до загрузки сохранения. Посему для тестирования изменения в файлах конфигураций надо перезапускать программу.

Довольно часто надо проверить некий фрагмент кода, заспавнить объект, проверить некую синтаксическую конструкцию и т.п.
"как мы обычно поступаем в этом случае"
1. Пишу скрипт и получаю вылет игры без лога, если влез в один из заранее прекомпилируемых файлов и сделал там тупую синтаксическую ошибку.
2. Выношу скрипт в отдельный файл и получаю вылет игры с до ужаса информативным сообщением в лог-файле "attempt to index global 'my_cool_script' (a nil value)".
Это значит, что тупую синтаксическую ошибку я сделал в файле my_cool_script.script
Можно до хрипоты говорить о пользе предварительной синтаксической проверки, но как часто мы её не делаем, не так ли?
3. Наконец-то умнею и проверяю скрипт на вшивость заранее. Запускаю игру, загружаю уровень.
загружаю уровень...
загружаю уровень......
Получаю вылет игры, лезу в лог и ищу в конце коротенькое сообщение, из которого следует, что надо поменять пару символов или добавить/стереть одну строчку.
4. Меняю скрипт, повторяю всё заново, скрипт отрабатывает, но делает не то, что мне надо. Чтобы изменения в скрипте вступили в силу, надо перегрузить уровень.
так что повторяю пп.3 и 4, пока не получу то, что мне было нужно.

Вот для частичного решения этой проблемы в своё время был сделан специальный тестовый полигон, который позволяет менять и вызывать определённый скрипт, не выходя из игры. Кроме того, часть ошибок (а именно ошибки Lua) блокируются и не приводят к вылетам. Полигон этот сэкономил мне кучу времени.


 
frontДата: Понедельник, 12.10.2009, 16:39 | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 152
Репутация: 229
Статус: Оффлайн
"Тестирование скриптов без обрушения и перезапуска игры"
Тестирование скриптов без обрушения и перезапуска игры
Ключевыми элементами являются две функции из стандартной библиотеки Lua:
dofile - позволяет загрузить и выполнить как chunk внешний файл.
pcall - позволяет выполнить произвольную функцию в т.н. защищённом режиме. Это значит, что любая ошибка интерпретатора Lua не выйдет за пределы функции, вызванной таким образом. Напомню, что обычно любая ошибка времени выполнения Lua передаётся хост-программе, т.е. игре, и вызывает её вылет.

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

Код
local res, err = pcall(my_proxy.start_chunk_from_file)
get_console():execute(res and "Succesfull!" or string.gsub(err, " ", "_")) --имитация тернарного оператора
pcall возвращает два значения. Первое - результат запуска. Если все прошло пучком, то true. Второе - добавочное значение с сообщением об ошибке, если ошибка была. Иначе nil.

файл my_proxy.script содержит всего одну функцию

Код
function start_chunk_from_file()
local chunk, err = dofile("..\\gamedata\\scripts\\test.lua")
if err then
get_console():execute("err="..tostring(string.gsub(err, " ", "_")))
end
end
dofile принимает имя файла со скриптом, загружает его и выполняет как функцию. Путём экспериментов я выяснил, что текущим каталогом Lua считает папку bin. Так что если хотим держать скрипт там, где и все остальные, то пишем путь относительно этой папки "..\\gamedata\\scripts\\test.lua".
test.lua - это отлаживаемый скрипт.
Обработка ошибок осуществляется аналогично pcall.

Так можно не выходя из игры и даже не перегружая уровень копаться в скрипте test.lua и запускать его по много раз, существенно менее рискуя обрушить игру. Особенно удобно, если есть два компа и сетка. В этом случае даже Alt-Tab не нужен. Редактируешь файл по сети на одном компе, а запускаешь в загруженной игре на другом.
Само-собой, если сделаем что-то, что фатально затронет игровую логику или что-то из ошибок категории 3, то обрушение может всё равно случиться. Сразу или в другом месте. В основном, в таких случаях уже ничего не поделаешь. Однако, довольно часто можно свести потенциальную ошибку времени выполнения движка к ошибке Lua. Например, если вызвать функцию get_console():execute(<аргумент>) с нулевым аргументом, то получим вылет без лога. Однако ничто не мешает сделать так:
get_console():execute("value="..obj)
В этом случае сначала будет выполняться конкатенация двух строк. Если obj будет равно nil, то получим ошибку Lua, а её тестовый полигон не пропустит, и обрушения игры не будет.

И ещё. Это всё работает для ТЧ. Для ЧН мне наладить такой же полигон не удалось. Что-то там изменено в движке, что вызывает у него аллергию на функцию pcall.


 
saproДата: Пятница, 20.08.2010, 01:37 | Сообщение # 3
Рядовой
Группа: Пользователи
Сообщений: 7
Репутация: 0
Статус: Оффлайн
Quote (front)
наладить такой же полигон не удалось. Что-то там изменено в движке, что вызывает у него аллергию на функцию pcall

объяснить???


Сообщение отредактировал sapro - Пятница, 20.08.2010, 01:37
 
frontДата: Понедельник, 23.08.2010, 09:30 | Сообщение # 4
Admin
Группа: Администраторы
Сообщений: 152
Репутация: 229
Статус: Оффлайн
Quote (sapro)
объяснить???

объясняй автору biggrin


 
saproДата: Понедельник, 23.08.2010, 16:19 | Сообщение # 5
Рядовой
Группа: Пользователи
Сообщений: 7
Репутация: 0
Статус: Оффлайн
А ты спец без ... как я погляжу.
 
  • Страница 1 из 1
  • 1
Поиск:

Для добавления необходима авторизация

Copyright Front Сайт оптимизирован под браузер Opera © 2025