AI IRL

Вы неправильно пишете животных

Животные – это платформы с очень ограниченной памятью, вычислительными способностями и возможностями модификаций. Разработчикам (допустим это Бог или ангелы) приходится выдавать практически гениальные низкоуровневые алгоритмы. Правда, большое количество хардкода вызывает характерные проблемы с отсутствием проверки в экзотических условиях. Та же фильтрация входных данных делается очень и очень криво.

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

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

Да, ещё о птицах, чтобы два раза не вставать. У них насквозь кривой модуль распознавания «свой-чужой». Что позволяет провести animal-in-the-middle-атаку с помощью подстановки звука птенца. Всё, что примерно совпадает по размерам и при этом передаёт открытую часть ключа, нужно покормить. Похожий баг есть у некоторых грызунов, что позволяет предположить проблемы с общей библиотечной функцией.

Теперь муравьи. Муравьёв довольно легко зациклить. Навигационный блок у них совмещён с системой приоритетов ОС, поэтому при построении циклического маршрута образуется «спираль смерти», затягивающая всё больше и больше ресурсов муравейника – и всё это зависает на 3-4 дня, пока муравьи не погибнут от истощения или что-то снаружи не поменяет навигацию.

А вот страус – вершина оптимизации. То, как именно в него впихнули пищеварение, вообще достойно войти в «Жемчужины программирования». Чтобы эта птичка нормально переваривала пищу, разработчик придумал заставить его натурально жрать камни. При беге камни трясутся и перемалывают зёрна. Теперь самое весёлое. Чтобы не писать отдельный код для поедания камней, страусу просто взяли и отключили центральный сектор зрения (как зайцу, но там это известный минорный баг). Поэтому когда страус целится в зерно, он попадает только в 30-50% случаев. Что легко позволяет набирать нужное количество камней, да ещё и с запасом. Именно поэтому страусы, запущенные на чистой виртуальной машине в зоопарке, испытывали проблемы с пищеварением до появления поддержки камней на уровне гипервизора. Кстати, коровы тоже жрут гвозди и иногда гравий, но это не в архитектуре, а просто техническая ошибка обратной совместимости.

Да, и ещё. Очень хорошая вещь – повторное использование кода. Часть функционала с камнями потом накатили на крокодила – чтобы ему нырялось лучше. Ныряется действительно лучше.

Проблемы энергопотребления решаются не менее гениально. С рептильной платформой всё ещё более-менее нормально (там просто нет долгих высокоуровневых процессов), и крокодил может сидеть сутки без движения до поимки мяса. А вот с теми же крупными хищниками всё пожёстче мобильных ОС. На 20 часов в сутки лев снимает все активные процессы и уходит в спящий режим. Примерно 4 часа он находится в активном режиме – рычит, размножается, сёрфит по саванне и находит новую зарядку в антилопе или зебре.

Дельфину вообще не всегда удаётся включать оба ядра мозга – только тогда, когда нужно делать что-то важное. Если вам встретился тормозящий дельфин – проверяйте, оба ли глаза открыты. Только один? Значит, он в спящем режиме и работает на одном ядре с пониженной тактовой частотой.

Медведь не всегда корректно выходит из hibernate-режима. Это же, кстати, касается некоторых растений, но там баг не так опасен. Растения легко перезапустить. И да, учитесь у тех, кто писал альбатроса. Альбатрос вообще спит в воздухе.

Теперь черепаха. Ей вместо того, чтобы прописать нормальный алгоритм обхода препятствий, захардкодили рефлекс убирания головы в панцирь. Теперь даже если она натыкается на крокодила, тот со своим молниеносным броском не успевает откусить ей голову. Побочный эффект – черепаха легко уворачивается от ножа мясника. Скорость обработки инструкций процессора не сравнится со скоростью работы интерпретируемого высокоуровневого кода у повара. Черепаху не обгонишь, критичные функции переписаны на ассемблере.

Белый медведь – отличный пример работы с солнечной энергией. Медведь прозрачный в УФ по меху и чёрный на коже. Это уже торжество инженера.

Жираф – сплошной костыль. Нет, в целом, понятно, что требования заказчика по высоте кроны несколько раз повышались по мере развития проекта. Но вот то, что вошло в релиз по водопоям и было пропущено на приёмке – это нонсенс. Жираф тупо не достаёт головой до воды(!) в обычном режиме. Ему приходится жутко вывернуться и почти сесть на шпагат, чтобы попить. Ясное дело, анонимусы-хищники этим нагло пользуются. Детёныша вообще пришлось укреплять – он в стабильном релизе падает с полутора метров при рождении.

Морской свинке и ряду рыб косо прописали задержки на прерываниях. Если обычное животное по очереди опрашивает прерывания вроде «нет ли опасности», «не надо ли попить», «не надо ли поесть», «не надо ли начать размножаться», «не надо ли лечь спать» и «не надо ли выполнять нестандартную процедуру» — и всё это без видимого переключения — то морские свинки делают sleep(1000); после каждой операции. Видимо, осталось с отладки и вошло в релиз.

Хорошей идеей было накатить код сборщика мусора в ОЗУ от золотой рыбки на белку – garbage collector с высокой вероятностью очищает и неиспользуемые указатели на места размеченных орехов и семечек. В результате благодаря белке вырастает много новых деревьев.

Вот индийскую кобру точно писал фанат Starcraft. Потому что, задумайтесь, где ещё можно встретить юнита, плюющегося ядом на два с половиной метра точно в глаз террану.

Ну и раз начали о нерациональности – вспомним того же осьминога. Километры нервной ткани просто потому, что кому-то было интересно написать его на brainfuck. Да если использовать эти отдельные модули управления присосками, ту же ткань – может получиться вообще ЦОД на колёсиках.

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

Тлей и других насекомых, а также ряд животных точно писал бешеный фанат рекурсии. Светлая мысль рождать некоторых уже беременными – просто вынос мозга для тестеров. Зато слонёнок деплоится 22 месяца — вот что значит не влезть в кэш процессора.

Кстати, пасхалка с бегемотом получилась смешная. Люди боятся львов, носорогов, змей – но только этот обаятельный толстяк целенаправленно бегает за человеком. И, внезапно, со скоростью до 30 км/ч. То есть догоняет даже велосипедистов.

У некоторых кошек не убрали аппаратный байпасс в районе шкирки. Стоит взять взрослую систему за это место, так сразу отключается двигательная активность. Что породило опасный баг с прищепкой, которым часто пользуются скрипткидди.

У курицы расслабленная лапа «защёлкнута», поэтому если поставить курицу на ветку, дождаться, пока она уснёт, а потом легко и быстро перевернуть, сработает рефлекс – и у вас будет курица, спящая вниз головой на дереве. Главное – подготовить почву и рассказать всей деревне про вампиров за день до зрелища такого курятника.

У собак и ряда других хищников и падальщиков косо прописано распознавание добычи. В одном из условий AND случайно заменили на OR, и вот результат — известный баг с запуском приоритетного процесса с атакой на пятно лазерной указки.

В общем, вы наверняка и сами можете продолжить.

P.S. Обратите внимание, что большая часть описанных уязвимостей до сих пор не исправлена.

© Сергей Абдульманов

FireLight Engine 2

Wooohooo! Тут недавно была «днюшечка» у… движка FireLight !

Его разработка стартовала 01.01.2014! Так что движок уже два года в разработке :)

И как раз где-то дней 10 назад была начата разработка его второй версии, FireLight Engine 2! В планах целый ряд фич и исправлений, например реализация PBR-материалов, улучшение интерфейса редактора, Deferred Decals, фоновая загрузка ресурсов и многое другое. Шутер Still Alive будет реализован на FireLight 2.

 

LightEd2На картинке выше изображена схема интерфейса редактора LightEd. Редактор создается на GUI системе движка.

 

Для редактора заготовлен Splash Screen, который должен появляться во время его загрузки, но пока он отключен :)

LightEdSplashFireLight

А еще есть «троллящий» движок Unity wallpaper:

UnityTrollingWallpaper

Забавно: 9-м коммитом в день создания движка, 1 января 2014-го года, в проект движка был добавлен Lua, но с тех пор он ни разу не использовался, потому что движок создается «без всякой этой скриптовой фигни» :D

 

Зачем писать движок сейчас, когда есть Unity5 и Unreal Engine 4 ? «Но если начинаешь писать движки, порой становится трудно остановиться»)) Свой двигЪ это круто, все исходники у тебя и ты в них разбираешься. Можно реализовывать то, чего нет в других движках. В FireLight-е, например, есть компонентная система материалов и skinned mesh instancing, позволяющий быстро рисовать тысячи персонажей со скелетной анимацией. А товарищ Try с gamedev.ru в своем Tempest Engine создает систему blueprint-ов как в UE4. В общем, удачи всем двигописателям! :)

WipeOut: Unreal Edition — Part 2: Animation Control

Продолжаем-с создавать Unreal-версию проекта WipeOut. В этой части мы займемся переключением анимации персонажа, которого в прошлой части героически притащили в мир Unreal.

 

Для начала разберемся как устроен ввод и анимация в шаблоне SideScroller.

В UE4 можно настроить привязку нажатия кнопок (осей джойстиков и т.д.) к действиям, и именно эта привязка используется как отправная точка управления персонажем. Для редактирования привязок (binding-ов) надо зайти в настройки проекта: Edit -> Project Settings; вкладка Input. Примечательно то, что в UE4 можно привязать произвольное количество кнопок и осей к одному и тому же действию.

В Unity тоже есть такая фича, там за это отвечает Input Manager.

 

Где же дальше используются определенные в настройках ввода действия Jump и MoveRight ? В коде класса персонажа, WipeOutCharacter.cpp. При этом в функцию MoveRight в качестве параметра будет передан Scale, таким образом по нажатию кнопок [A] и [D] будет вызван MoveRight с разным направлением и персонаж сможет ходить не только направо, но и налево. Основную работу по перемещению персонажа выполнит класс ACharacter, от которого унаследован WipeOutCharacter. ACharacter — класс из GameFramework-а, на котором основаны шаблоны игр, предлагаемые движком.

 

 

 

 

 

 

 

 

 

 

 

 

 

Но код выше занимается только перемещением персонажа. Кто же управляет анимацией ? Её управление полностью сделано BluePrint-ами. Да-да, выбрав группу шаблонов на базе С++ кода, мы все равно вынуждены работать с блупринтами. Рассмотрим же как оно сделано. Блупринт анимации для персонажа из примера находится в папке Content\Mannequin\Animations и называется ThirdPerson_AnimBP. Откроем его и посмотрим что там!

Хм. Блупринты. Пора уже смириться :D Итак, все начинается с события Event Blueprint Update Animation, красный узел слева. Оно вызывается каждый кадр, т.е. постоянно. Сначала мы спрашиваем PawnOwner-а у AnimInstance-а (объект Self) и проверяем его на правильность (вдруг его нет, и все такое). Если у нас есть PawnOwner, то у него получаем компонент MovementComponent, у которого мы спрашиваем падает ли персонаж (IsFalling). Возвращенное значение записывается в переменную блупринта IsInAir (красный блок Set вверху). Потом мы у PawnOwner-а получаем вектор скорости (Get Velocity), узнаем его длину (т.е. саму скорость) и записываем скорость в переменную блупринта Speed (зеленый блок Set внизу). Значения Speed и IsInAir будут использованы для смешивания анимации.

Если записать это все кодом, получится 5 строчек.. 5 строчек, КАРЛ! Вот такой код:

 

 

 

 

 

Но это лишь малая часть того, как устроена смена анимаций. Внизу редактора блупринтов есть вкладка My Blueprint. В ней есть раздел с переменными о которых шла речь выше — Is In Air и Speed. Можно добавить новую, нажав на [+].

И тут же есть вторая часть блупринта — AnimGraph. AnimGraph/Default это целая машина состояний, именно она переключает анимации.

Тут у нас состояния анимации и правила перехода между ними. В самом начале мы находимся в Idle/Run. Каждому состоянию и правилу перехода соответствует свой блупринт.

Например из Idle/Run в JumpStart мы переходим как только выставлен флажок Is In Air. Из JumStart в JumpLoop — когда доиграется анимация JumpStart. Из JumpLoop в JumpEnd когда Is In Air = false. И наконец возвращаемся в Idle/Run когда доиграется анимация JumpEnd. Состояние JumpStart это такой простой блупринт, который играет указанную анимацию и передает её в текущую позу модельки:

Почему нет отдельных Idle и Run ? И где мы используем Speed ? О, сейчас мы ответим на эти вопросы! Развернем состояние Idle/Run. Так как состояния это тоже блупринт, то там можно творить что угодно. И Idle/Run передает значение переменной Speed в BlendSpacePlayer:

Что же такое BlendSpace ? BlendSpace это отдельная схема смешивания нескольких анимаций в зависимости от внешнего параметра, в данном случае в зависимости от скорости. Откроем BlendSpace для IdleRun.

В зависимости от значения Speed, идет смешивание анимации Idle и Walk, а также Walk и Run. Для этого заданы лишь три точки, каждой соответствует значение скорости и клип анимации. Можно перетаскивать анимации и добавлять новые точки. Таким образом, можно в любой момент заменить воспроизведение одной анимации на красивое смешивание нескольких в зависимости от некоторого параметра.

 

Создание своего Animation Blueprint и Animation BlendSpace.

Что-ж, довольно мощный получился обзор того как устроена анимация в шаблоне SideScroller. Но не менее важно знать как создать необходимые блупринты самостоятельно. Тем более персонаж WipeOut-а уже жаждет бегать по уровню!

Вся магия со смешиванием анимации и красивой её интерполяции основана на том, что модель привязана к скелету. Кроме того, со скелетом связаны подходящие для него анимации. Поэтому и пункты меню для создания блупринтов анимации привязаны к скелету модели. Выбираем скелет и находим в меню пункт Create -> Anim Blueprint.

Новый блупринт встречает нас .. полным отсутствием чего-либо)) Он ничего не умеет еще, бедняга. Но не зря же трудились товарищи из Epic Games! Скопируем хотя-бы Event Graph из рассмотренного выше примера. Для этого сначала вручную добавим переменные IsInAir? (тип boolean) и Speed (тип float). Теперь откроем Event Graph из примера, выделим все узлы и скопируем их. Открываем наш блупринт, вставляем узлы туда. Нажимаем кнопку компиляции вверху. Похоже все в порядке.

Теперь переходим к AnimGraph. Как и в шаблоне, создаем новую машину состояний (State Machine). Правой кнопкой мыши откроем меню и создадим новую State Machine. Добавим состояние Idle/Run. Можно прямо начать строить стрелку к новому еще не существующему состоянию и редактор предложит его добавить!

Откроем созданный Idle/Run. Надо перетащить переменную Speed на блупринт. Мы хотим прочитать её значение, поэтому в меню выбираем Get. Ещё нам понадобится BlendStatePlayer. И, что радует, UE4 предложил уже ранее созданный для персонажа BlendState! Мелочь, а приятно: не придется устанавливать свойство BlendSpace плеера.

Теперь осталось соединить стрелочками все три узла и нажать Compile :)

Похоже все окей, и анимация действительно реагирует на изменение параметра Speed.

Я не буду детально описывать создание BlendSpace-а, т.к. пункт меню Create -> Blend Space находится рядом с пунктом создания Anim Blueprint в меню скелета, а добавление анимаций в него делается простым перетаскиванием на шкалу :) Вот что у меня получилось:

 

Замена модели персонажа из примера на своего.

Мы подготовили модель и анимации. Теперь надо заменить модель из шаблона на нашу.

Блупринты в UE4 работают почти как префабы в Unity. Чтобы поменять персонажа, надо открыть его блупринт. В шаблоне SideScroller блупринт персонажа находится в файле Content/SideScrollerCPP/Blueprints/SideScrollerCharacter. Это блупринт, созданный для C++ класса WipeOutCharacter, и он содержит некоторые важные данные для его работы. Нам понадобится поменять меш (Skeletal Mesh) на свой и Anim Blueprint Generated Class на созданный нами блупринт анимации (PlayerAnimBP). Затем нажать кнопку Compile :)

 

Настало время для первого видоса ^^

А в следующей части мы научим персонажа стрелять!

WipeOut: Unreal Edition. Part 1: Player Model Import

Что за проект WipeOut ?

Есть у меня один заброшенный проектик на движке Unity — WipeOut, это шутер с видом сбоку. В него даже можно поиграть, вот ссылка на web-версию (unity web player).

 

Так вот, настало время сделать его вторую версию, уже на движке Unreal Engine 4!

Я планирую рассказывать о процессе создания UE4-версии игры, и начну прямо сейчас!

 

Сначала, пара слов о движке

Во-первых, сейчас использование движка бесплатное, надо лишь платить 5% с прибыли когда игра дойдет до релиза (т.е. будет выпущена в магазин Steam, Desura или иной подобный).

Во-вторых, что нам понадобится чтобы начать работать с UE4 ?

  • Windows 7 SP1 или Windows 8,
  • Microsoft Visual Studio Community Edition 2015.

 

Для тех, кто раньше использовал Unity, Epic Games создали документ UE4 for Unity Developers.

 

 

Итак, начнем!

UE4 предлагает несколько шаблонов игр. Все шаблоны есть в двух версиях: на основе BluePrint-ов (визуальное программирование) и на основе C++.

 

WipeOut-у больше всего подходит шаблон SideScroller. BluePrint-ы для слабаков, выбираем C++ :)

Если на этом этапе еще не установлена Visual Studio 2015 Community, то появится кнопка для установки. После выбора шаблона, папки и названия останется только нажать кнопку Create Project.

 

UE4 и git/svn

Чтобы в Unity использовать систему контроля версий, нужно было в настройках включать Visible meta files, после этого можно было удалять папку Library и добавлять её в игнорируемые. В UE4 можно удалить и заигнорить папки Saved, Intemediate и некоторые другие.

 

 

Импорт модели игрока. Материалы и анимация.

Для того чтобы добавить в проект новые модели и другой контент, можно просто скопировать новые файлы в папку Content (можно создать какую-нибудь подходящую подпапку при желании).

 

Как только мы добавим модель игрока в проект, появится окно импорта.

Я убрал галочку с пункта Import animation, чтобы добавлять файлы анимации отдельно.

В папке где лежит fbx моделька появится множество файлов: файл скелета модели, файл привязки физики к скелету, файлы материалов и файл самой модели (SkinnedMesh). Если вытащить на сцену файл модельки, увидим как она выглядит в движке.

Модель персонажа игрока для WipeOut взята из демки AngryBots (Unity). Модель в формате fbx, а текстуры в tiff.

 

Хранить текстуры в TIFF-формате весьма оригинально.. обычно используют PNG, JPG, TGA или PSD. Unreal Engine не считает TIFF настолько распространенным форматом, поэтому отказывается «видеть» эти текстуры.

Что же будем делать ? Да просто сохраним текстуры в PNG формат!

Но все немного осложняется тем, что это TIFF с альфа-каналом: по традиции юнити, в альфа-канале diffuse текстуры для непрозрачных объектов хранится specular map, карта блеска. Как оказалось, не все редакторы нынче умеют правильно пересохранить TIFF в PNG. Paint.NET, например, смешал цвет и альфу жутким образом. Поэтому у меня получилось две текстуры: в одной правильный цвет, а в другой правильная прозрачность :)

 

В отличие от Unity, материалы в UE4 создаются из произвольного количества узлов. Например, чтобы добавить узел с текстурой достаточно перетащить файл текстуры в это окно. На скриншоте видно «испорченную» текстуру из альфа-канала которой берется Specular.

 

Добавление анимации.

Решил показать как добавляются анимации для уже существующей модели. Просто скопируем файл модели (в исходной модели все анимации в одном файле) и назовем его Player_Run. Выключим импорт меша (т.к. в файле нам нужна лишь анимация). Затем необходимо указать для какого скелета предназначена эта анимация. Выбираем Player_Skeleton. На этот раз раскрываем вкладку Animation и устанавливаем начальный и конечный кадры анимации.

Теперь можно указать анимацию модельки. Для этого выберем модельку персонажа в сцене (да, клевая желтая обводка в UE4!) и изменим режим анимации (Animation Mode) на Use Animation Asset, а Anim To Play на нашу только что импортированную анимацию. Вот что получится:

Вот так выглядит игра если нажать кнопку Play. Все-таки рендер в UE4 чертовски красив даже без особой настройки :)

Что-ж, на этом закончим первую часть создания WipeOut 2 на UE4! В следующей части мы займемся управлением анимацией. Вторая часть: управление анимацией.

Still Alive — still alive!

Да, проект еще жив и намерен дойти до финала конкурса шутеров ^^ Тем более, что конкурс продлили до 10 декабря, уииии!

Пора порадовать некоторыми work-in-progress скриншотами))

 

 

 

А знаете ли вы что?..

У юнити есть мануал для перехода со своего движка.. на юнити!! xD

 

Руководство по переходу с собственного движка

Крупные и небольшие студии отказываются от собственных разработок в пользу индустриальных движков.

 

 

Еще раз.

Руководство. По переходу. Со своего движка. НА UNITY!!! xD

Возможно немного не очевидно почему у меня это вызывает такую реакцию. Объясню.

Как можно написать мануал с перехода с неизвестной, кастомной технологии ? Они же не знают чего там сделано в кастомном движке. Может там весь рендеринг на вокселях, бывает и такое! Плюс, обычно компании, которые пишут свои движки, делают это с определенной целью: сделать удобно, реализовать то, чего нет у остальных, применить какие-нибудь крутые оптимизации или реализовать специфичные для игры фичи. Даже сама архитектура (структура проекта, компонентов, пайплайн работы с графикой и ресурсами) может сильно отличаться, и сделать такой переход в принципе невозможным.

Таким образом, созданный «мануал» содержит скорее маркетинговые аргументы в пользу Unity. За подтверждением далеко ходить не надо: в мануале есть раздел «Как создать ААА-игру».

 

 

Still Alive — Weapons & Enemies (WIP)

Новости проекта конкурсного шутера Still Alive

Добавлен револьвер, переключение оружия, летающие враги, механический паук и эпичный фейерверк в конце видео (just for fun).

 

Still Alive — AI & FX

Новости о конкурсном проекте шутера Still Alive.

 

В игре словно из ничего появляются псевдо-фичи:

— Шотган стреляет ^^
— Тупой AI :)
— Разрушаемые ящики
— Декали (да-да, декали от разрушенных ящиков в воздухе висят, знаю)
— Потрясающий звук и эффекты попадания в машину-консервную-банку

Still Alive — Главное Меню

В проекте Still Alive появилось главное меню. Игра создается для конкурса шутеров на GameDev.ru. Игрок попадает в заброшенный город, а там его ждут неприятности. Но отказаться нельзя: они же ждут!

Still Alive — Logo

Ну что, друзья, с чего начинается разработка любой игры ?

С дизайна, концепта, сеттинга и сценария ??? Фи, нет конечно! Она начинается с заставки и названия! :D

Заставка и название у нас появились) Заставка сделана в движке, т.е. это не видео ролик. Только риалтайм, только хардкор. Магия шейдеров и скриптов :)

 

Но на самом деле, концепт тоже есть, не переживайте :)

А еще есть тема на GameDev.ru.