Взгляд на ботов изнутри или как создать вменяемый ИИ и постараться не сойти с ума
Меня зовут Николай Тупицин и я гейм-дизайнер. А еще и scriptwriter в обоих смыслах этого слова – и сценарист, и скриптовик.
ПЕРВЫЙ БОТ И КОНТРОЛЛЕР ПЕРСОНАЖА
Изначально мы были сосредоточены на ПВП контенте, но потом стало понятно, что бросать неподготовленных людей в мясорубке чересчур жестоко. Недолго думая мы решили добавить простейшую тренировку, в которой должны были быть простейшие боты. С этого и началась разработка ботов в Warside.
Первого бота звали Mr.Chicken и все что он мог делать – бегать от игрока по прямой, а если в него стреляли – приседать и бояться. Если посмотреть на него изнутри, то весь его интеллект представлялся скриптовой процедурой, вызывающей каждый кадр, и дергающей клавиши управления. Собственно, эта особенность так и осталась – ИИ управляет ботами так же как игрок, нажимая кнопки и целясь мышкой. Конечно, есть разница, но она небольшая. Именно с этим связано большинство ограничений на количество ботов – ведь ресурсы, расходуемые на бота, будут всегда больше ресурсов, расходуемых на игрока, сколько ни оптимизируй ИИ.
Вообще золотое было время: простые боты практически не доставляли проблем, в их умах не проскальзывала мысль забаговать, начать беспричинно убивать все живое или образовать Скайнет и начать порабощать Землю. Жаль только, что и делать они практически ничего не умели.
Помимо контроллера персонажа, то тут, то там все еще можно найти некоторые следы этого золотого времени. Например, на карте «База Элайза-66» внимательные игроки смогут найти странный вырезанный прямоугольник глубоко под землей. Эта «курилка» была предназначена для «хранения» ботов из спавнеров и некоторых комнат. Из-за трудностей повторного спавна ботов там, где необходимо, приходилось спавнить ботов именно в этой курилке, и уже потом телепортировать их куда надо. Однажды, большой паук вывалился из курилки и умер, так и не появившись на арене, где его ждали игроки. Чтобы избежать такой ошибки в дальнейшем, курилку сделали большой, чтобы боты в ней помещались.
КОНЧЕННЫЕ БОТЫ ИЛИ ЧТО ТАКОЕ FSM
Однако вскоре стало понятно, что примитивных ботов недостаточно. Даже для тренировки требовались болванчики, способные на мало-мальски разумное поведение, к тому же, не покидали настойчивые мысли о создании ПВЕ. Старая добрая процедура трещала по швам и не годилась для эмуляции поведения, ведь линейной программой удобно решать одну конкретную задачу, а не целый класс с разными условиями и зависимостями. Поэтому я решил, что нужно как можно быстрее озаботиться переводом ботов на конечные автоматы (о которых вы узнаете ниже), сначала в скриптовом формате, а потом, получив и специальную структуру под это дело, от серверных программистов.
Картинка, изображающая пример конечного автомата. Кружки – состояния + действия в них. Стрелочки – переходы с написанными на них условиями.
Конечные автоматы (FSM, Finite State Machine), как подсказывает википедия, это модель дискретного устройства, имеющего один вход, один выход и в каждый момент времени находящегося в одном состоянии из множества возможных. Применительно к ботам это сухое определение можно развернуть так – FSM это алгоритм бота, в котором решение о том, что делать принимается исходя из 2-х вещей – внешнего условия и внутреннего состояния бота.
Картинка, представленная выше, выглядит в коде как то так:
Как видите, подобный подход достаточно удобен, а главное хорошо подходит для описания бота. Ведь практически так задачи по ботам и ставятся – «Ну мы хотим, чтобы он, атакуя (читать в состоянии «атака») всегда держался недалеко от игрока (читать «условие расстояния до игрока»), но если игрок подходит слишком близко – убегал (читать, если выполняется условие «ИГРОК БЛИЗКО» перейти в состоянии «УБЕГАТЬ»)».
Конечные автоматы позволили делать множество разных ботов, у каждого из которых были свои настройки. Для облегчения создания бота были добавлены шаблоны, которые определяли все – от вооружения до тактики. Иногда случались проколы, и появлялись курьезные сочетания. Например, летающему роботу-пчеле был случайно присвоен шаблон милишника, и в итоге нас на карте встречали кровожадные пчелы с тесаками.
НУЖНО БОЛЬШЕ БОТОВ
Размах ПВЕ составляющей постоянно увеличивался, заменив простых болванчиков с тренировки. На носу был режим выживание, в котором боты спавнились кучами, но ресурсы сервера не были бесконечными. Ботам достался один жуткий минус от процедуры – решение о том, что делать принималось каждый кадр. Каждую толику времени все боты (включая мертвых или еще не отспавненных) на карте скрипели мозгами над принятием тривиального решения «Продолжать ли делать то, что делал, если ничего не изменилось». При малом количестве ботов, на это не обращаешь внимания, но стоит использовать реально большое количество – и боевой сервер ПВЕ неимоверно раздувается, захватывая все ресурсы. О том, что происходило, если запустить сразу несколько ПВЕ миссий, думаю, можно догадаться.
Спасение пришло от серверных программистов, которые добавили механизмсобытий, заодно расширив с помощью них функционал конечных автоматов. По сути, теперь боты думали, что делать не каждый кадр, а только тогда, когда происходило что-нибудь значимое. Данное нововведение позволило существенно разгрузить сервер, и создавать действительно большие группы ботов.
Поскольку систему вводили в короткие сроки, посыпалось много забавных курьезов. Например, из-за небольшого недосмотра, боты продолжали работать после смерти и реагировали на приближение врага к их трупу, даже пытались его атаковать. Получилось, по-моему, только у паука-суицидника, который после смерти начинал работать как натуральная мина. Другой курьез был в том, что от ботов можно было прятаться прямо перед их носом. Достаточно было подкрасться к боту, отвлеченному другим игроком, и ничего не делать – новых событий не происходило, и бот просто не знал о вашем существовании.
НУЖНО ЕЩЕ БОЛЬШЕ БОТОВ
Несмотря на (или благодаря?) механизм событий, мы поняли, что нам нужно больше ботов, причем разнообразных в собственном поведении. Это требование упиралось в большую внутреннюю связность автоматов. Большая связность означает, что, если я хочу изменить в готовом автомате одно состояние, мне придется переписывать чуть ли не весь автомат (точнее все состояния, что связаны с изменяемым куском). А подобное переписывание крайне отрицательно сказывается на скорости создания ботов.
Сначала я пытался разделять автоматы на маленькие куски, которые повторялись из автомата в автомат (например, состояние «Покой»), но из этого не вышло ничего путного – для некоторых ботов приходилось переписывать даже состояние «Покой», пусть даже все переписывание и заключалось в добавлении одного условия и соответствующего действия.
Просмотрев некоторое количество материалов по этой проблеме, я наткнулся на достаточно элегантное решение. Автор предлагал использовать вместо одного конечного автомата, описывающего полное поведение бота, несколько таких и переключать их специальной процедурой. То есть мы делили автомат на несколько «поведений» – например, поведение в покое, поведение в атаке на врага или поведение на выполнении миссий, которые уже выбираются исходя из каких-либо условий. Это позволяет переписывать не всего бота, а только поведение, которым он отличается, а значит, скорость работы по созданию новых ботов растет.
После введения такой процедуры решений писать стало действительно легче, а ошибки даже забавнее. Одна такая чуть не разрослась в детективную историю. В режиме выживание боты вели себя вполне естественно, но ботов с дробовиком всегда что-то убивало около объекта который они должны были разрушить. При этом судя по взрыву стреляли из ракетницы. Я долго искал таинственного убийцу, пока наконец не увидел, что их поведение «уничтожить объект», повторяло поведение пауков суицидников. И они действительно подбегали к объекту и взрывались, хотя во всех остальных случаях вели себя естественно.
Идеальная синхронизация, или что происходит когда противники равны и управляются одним и тем же интеллектом. (Слева направо: Бот корпорат, Я, Бот коммунар).
В БЕСКОНЕЧНОСТЬ И ДАЛЬШЕ
Улучшать ботов можно и дальше. Помимо усовершенствования структуры непосредственно «Мозга» ботов, так же происходят и изменения вспомогательных процедур. Агросписок оформился из скриптовой составляющей, Pathfinding (система поиска пути) также пришел на замену скриптовым процедурам перемещения, даже некоторые типы атаки были заменены низкоуровневыми эквивалентами. Текущая структура ИИ позволяет проводить подобные замены быстро и безболезненно, и я считаю, что её нам хватит надолго. Впрочем, если у кого-то есть конкретные предложения (с четким обоснованием) буду рад услышать.
И помните, у ботов тоже есть душа!
- 24 июня 2014, 17:06
Чего-то носятся-носятся с этой игрой. Уже уйма постов. Не поленился - сходил на сайт. Обычная же фритуплейка!
Ну, смотря что вы вкладываете в слово "обычная". Если говорить именно про модель распространения, то наша модель монетизации может приятно удивить.
А если про жанр - ММО сайд-скроллеры можно по пальцам пересчитать.
Ну так интерес и ценность инфы именно из-за кулис, что да как делается и какие сложности возникают, что и почему работает хорошо или плохо.
Похоже, что нет:
а) Удобного редактора. То, что вижу на картинках, кажется неудобным.
б) Нет влияния рандома. Без рандома всё грустно.
в) Могу ошибаться, но сложную ветвистую структуру поведения написать невозможно, ведь так? Например, ии персонажа, поддерживающего диалог с десятком фраз, атакующего, отступающего, скрывающегося, меняющего отношение к игроку, разговаривающего с другими нпс.
Вот ответ нашего геймдиза:
a)На приложенных картинках нет редактора (да и речи о нем не шло). Это схемы и таблицы приведенные для разъяснения самого МЕТОДА создания ИИ, чему собственно и посвящена статья. Для расстановки ботов, выбора из шаблона поведения, задания вейпонтов у нас есть map editor, который является по сути просто тулзой, о которой я не вижу смысла говорить. Здесь рассматривается непосредственно реализация ИИ, сама суть "мозгов" бота, а для их описания ничего лучше программного кода так и не придумали.
б)Рандом легко подключаем, если того требует задача. Пример - робот пчела (которую вы можете видеть с тесаком, на картинке в статье), перемещающаяся случайным образом, для того чтобы уворачиваться от игрока. Плюс все роботы вооружены оружием, подчиняющимся общим законам боевого мира и имеющим настраиваемый разброс, который приносит дополнительную порцию желаемого рандома.
в). Прошу обратить вас внимание на последнюю часть статьи ("НУЖНО ЕЩЕ БОЛЬШЕ БОТОВ"), в которой описывается реализованный нами механизм "процедуры решений". Данный метод также называется "деревом решений", и по сути своей является той самой сложной ветвистой структурой о которой вы говорите.
По моему, лучшее решение это редактор.
Например так: в коде игры прописывается реализация (1)абилок бота и (2)рецепторов бота.
Абилки это: открыть дверь, прыгнуть, атаковать объект, поставить мину, подобрать объект, и так далее. Рецепторы бота это: вижу объект, слышу объект, мало здоровья, закончились патроны, ай-я-упал-в-лаву, и так далее.
А вот в редакторе, как в блок-схеме, создатель интеллекта мышкой расставляет ветвистую последовательность. С объектами-абилками, между которых располагает стрелочки-рецепторы. И с внутренними переменными, в которых идёт счёт.
Как я понял, у вас всё упрощено: железно прописывается в коде-скрипте. Что не обладает наглядностью и удобством редактирования. Особенно при значительных размерах ии.
По-хорошему нужен редактор. Прописывать всё в скрипте это дешёвое решение. Оно экономит вам время на написание редактора, но не позволит быстро писать более-менее сложный ии с хотя бы несколькими десятками абилок.
Просто точка зрения, спорить не буду.
Ответ Николая:
Визуальное программирование это прекрасно, но и оно дает существенные ограничения, например, то что описанная вами структура достаточно плоская, и подходит только для игр в которых можно выделить эти самые "рецепторы" и "абилки" (а куда податься шутерам, RTS и множеству других жанров?).
Так же вы почему то замеряете сложность ИИ исключительно количеством этих самых абилок (а если требуется добавить еще одну группу вещей, те самые "внутренние переменные" которые вы упомянули вскользь?).
Но даже следуя ваши допущениям, рассмотрим случай действительно большого количества рецепторов, абилок и "внутренних переменных". Мне почему то кажется, что граф будет крайне сложен для того, чтобы в нем разобраться и будет похож на графы связей у киношных сумасшедших сыщиков (по моему в Гае Ричевском Холмсе такой показывали).
Но тем не менее визуальное программирование, которое как мне кажеться, вы подразумеваете, это действительно нужная и крайне необходимая вещь, создание которой должна провоцировать индустрия. Лучше всего об этом описано у Брета Виктора, с работами которого я настойчиво рекомендую ознакомиться всем. Вот сайт http://worrydream.com/, там внизу самые лучшие демки это Inventing on Principle и Stop Drawing Dead Fish.
... удобством его редактирования.
Наглядный пример. Представьте, что карту уровня-этажа, его объекты вы не расставляете мышкой в редакторе, а прописываете кодом. Буквально, в коде прописываете, что по координатам 6547.456 и 3465.456 будет "металлическая платформа". И так для всех объектов уровня.
Удобно будет? Сможете вы легко и быстро набросать пару сложных тестовых уровней-этажей? То же самое и с ии.
М. Ты путаешь удобство проектирования с финальным продуктом. при проектировании удобно мышкой всё накидывать, а вот функционировать всё будет куда быстрее, если компактно описано на низком уровне и считывается/воспроизводится с соответствующей высокой скоростью.
И помните, у ботов нет никакой души, это всего лишь конечные автоматы! :)
Спасибо, читать было интересно!
Есть такая штука - дерево поведений. Я так понимаю, вы пилите игру на юнити. Там оно бесплатным ассетом идёт. Сам не пользовался но читал что это хороший апгрэйд на FSM. Вообще очень распространённая фигня и думаю что она есть реализованная в любом 3Д двиге.
Если говорить про хороший ИИ. Ну прям ваще хороший. То лучше поглядеть на GOAP (Goal Oriented Action Planning). Собственно, агентная система, где бот не умеет "читерить", т.к. все сигналы о внешнем мире получает таким же способом как игрок. И имеет специальный модуль анализа окружения и выстраивание пути достижения целей. Вся прелесть этой штуки в том, что она практически полностью делается на логике.
В кратце идея - агент считывает из внешнего мира какие-то параметры. У него так же зашиты цели - которые заданы некоторыми наборами/значениями параметров. Как только он понимает какая ему цель нужна - начинает работать алгоритм её достижения. А именно - функции которые пытаются улучшить полученные параметры до целевых. Вещь получается достаточно гибкой.
Я читал диссертацию каких-то челов которые анализировали эту штуку на UT2. Результаты вышли интересными. Так же они приводят там архитектуру этой системы. ИМХО не сильно сложно выглядит.
На практике надо по игре смотреть. Если нужно имитировать реальных игроков(тем паче в коопе), то стоит ковырять GOAP. Если так просто вражин сделать, то дерево поведений пойдёт. Если делать обычный сингловый платформер, то лучше делать примтивную FSM на 1-2 состояния и догоняться хорошим левелдизайном. При хорошем левелдизайне даже двигающийся по кругу шарик может доставить игроку много проблем.
Ответ Николая:
Нет мы не делаем игру на Юнити, да дерево поведений это классная штука, да именно подобие его нам и удалось сделать самостоятельно и теперь мы рады и его используем.
Насчет GOAP это действительно интересная система, но боюсь плохо настраиваемая. Современный геймдизайн требует от мобов предсказуемого поведения, которое могли бы настраивать геймдизайнеры, а так, ну разве что для ИИ компаньона в коопе. В принципе, если я правильно понял систему, агента можно "надрессировать" под нужное поведение, но использовать методы машинного обучения для множества мобов, это, по крайней мере пока перебор.
Насчет левелдизайна полностью согласен. Более того, как по мне - плохой левелдизайн может слить любой Убер-ИИ.
На самом деле современный гэймдизайн жаждет увидеть непредсказуемое поведение, просто никто пока этого не знает. Это послезавтрашний день. И это действительно делает игру интересной. Люблю переигрывать DmC именно за мобов-мечников, чьи действия абсолютно непредсказуемы.
Полагаю, хорош именно баланс предсказуемости (ну что пеший бот не будет летать) и непредсказумости (что он сумеет влезть в какую-то дыру, забаррикадироваться и отстреливаться оттуда, делая вид, что патроны кончились)
Кстати от «кончившихся патронов» мне знатно припекло в DeusEx HR. То ли там не так скрипт сработал, то ли так задумано, то ли я не заметил как затупил. В общем бот орёт то ли «чёрт, перезарядиться надо» то ли «патроны кончились», вылазию на радостях и мне очередь в лоб с криком «попался!» Обычно они тупили, паля в моё укрытие но порой очень грамотно перебрасывали гранату через верх.
То есть такое поведение, где бот может схитрить, затаиться, подловить. Плюс выбор тактики поведения в зависимости не только от деталей собственного состояния (оставшееся здоровье, патроны), но и от соотношения оного с наблюдаемым (баланс своей пушки против пушки противника, сколько ботов против скольки игроков).
С давних времён как ботов отстреливают? Находят место, в котором бот затупляет/бессилен, заводят, нападают. В том же DeusEx HR эти ребятки не умели присесть и заглянуть в вентиляцию и отойти подальше, чтобы её обстрелять. В итоге подходили и получали прививки от бодрости из транквилизаторного ружьишка.
Именно поэтому я не перепрохожу DeusEX HR больше. Даже на харде враги ведут себя очень тупо. Я за первое прохождение изучил их поведение и во второе прохождение мне было скучно играть уже. Хочется чтобы они замечали именно отсутствие напарника, например через какое-то время. Типа "Что-то Джона давно не видно, он снова что ли в толчке залип?" идут в толчок, а там его нет. Поднимают тревогу. А так получается что любую тревогу можно легко отсидеть а врагов вырубать по одному.
А вот в DmC не так. Всегда есть риск что враг поведёт себя не так как ты ожидаешь. Причём даже самый слабый враг. И сколько ты ни тренируйся - риск всегда остаётся. Можно выработать тактики, но они не всегда работают.
Cкажи, пожалуйста, про какую часть DMC (их ведь несколько вроде?) идёт речь? :3
Думаю, что он про ту, которая так и называется – DmC: Devil May Cry
Тогда не знаю о какой нелинейности поведения речь. Всю прошел, стандартные болванчики для битья.
Да, этого стелсам не хватает люто. Когда один пропал, начинают беспокоиться, проверять. Много пропало/перебито — паниковать, агрессивно реагировать на любой шорох. Остался один из толпы — прятаться, зажиматься в угол, баррикаддироваться и отстреливаться до последнего патрона.
Интересная и легкоусвояемая статья про FSM. Спасибо. :)
В интернете мало русскоязычных статей о AI.
В "НУЖНО ЕЩЕ БОЛЬШЕ БОТОВ" написано про "Hierarchical FSM".
Дальше по удобности в кодировании ботов идет "Behavior Tree".
Вот хороший перевод на русский статьи про кодинг AI: Кулинарный путеводитель по архитектурам AI
Ответ Николая:
Спасибо за статью, весьма интересная, но по-моему автор перебарщивает с мексиканской кухней =) Насчет текущей реализации у нас (описанной в "Нужно больше ботов") спорный вопрос. Это гибридная модель, где вместо верхних уровней находиться дерево решений, а поведения реализованы конечными автоматами. Она находится четко посередине между Behavior tree (насколько я его понимаю), и HFS.
Еще хочу!
Статья хорошая, но, на мой взгляд, в ней описываются совершенно очевидные вещи.
Для кого-то очевидные, для кого-то новые, кому-то просто напоминание. Я например далеко не разработчик, не программист, просто имел дело с алгоритмами и играми и понимаю. И подобные вещи, которые я говорил начинающим игропрограммёрам (порой окончившим 4й—5й курс по близкой теме) вызывали реакцию «Блин, я об этом даже не думал!»
Ответ йео:
Статью не читал.
Конченые боты?
Это юмор нашего геймдизайнера =)