Unreal engine 4 игры на движке. Видео: дебютный трейлер Dishonored

Новой мобильной Lineage 2 на Unreal Engine 4 мы решили составить небольшую подборку интересных ремейков игр на этом движке, которые заслуживают вашего внимания.

Итак, топ-5 ремейков игр на Unreal Engine 4. Поехали!

1.

Анонс ремейка легендарной Final Fantasy 7 на конференции E3 2015 стал для многих людей главным событием того года.

В последствии, на PlayStation Experience 2015, был показан трейлер, содержащий в себе несколько секунд впервые показанного геймплея с участием Клауда и Баррета в самом начале игры.

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

2.

3.

22-летний художник 3D-окружения Киммо Каунела из Финляндии на протяжении всего предыдущего года работал над проектом The Last Stop , вдохновлённым творением студии — игрой . Киммо удалось создать потрясающую карту, показывающую, как бы выглядела игра, будь она выпущена на движке Unreal Engine 4.

У парня есть аккаунт на Deviant Art и собственный сайт , где можно посмотреть его последние работы. Этот проект, по словам автора, научил его работе с Unreal Engine 4.

4.

Энтузиаст Аирам Эрнандес поделился в начале этого года видео с любительским ремейком первой части , над которым он работает в одиночку.

Работа Эрнандеса использует модифицированную версию графического движка Unreal Engine 4. По его словам, сперва он хотел только воссоздать остров Тень Моисея (Shadow Moses) на новой технологии, чтобы знакомые с оригиналом геймеры и новички могли изучить его достопримечательности. Однако после того как на техническую демоверсию обратили внимание зарубежные СМИ, Эрнандес решил взяться за полноценный ремейк стесл-экшена.

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

5.

Моддер с ником Logithx вознамерился сделать ремейк культового шутера . Энтузиаст работает над воплощением антиутопичного Города-17 из HL2 с помощью Unreal Engine 4. Примерную дату окончания работ автор назвать пока не может — все пока еще на ранней стадии.

Logithx много времени работал над ремейком Half-Life 2 на прошлой версии движка от Epic — Unreal Engine 3. Однако когда компания начала распространение мощного UE4, он решил начать работу с нуля — и уже на новой технологии.

6.

«Как так, вы же сказали Топ-5 — откуда 6-й пункт?» - спросите вы.

К черту правила! Это же на Unreal Engine 4! Вы только посмотрите на эту графику! Автор проекта по переносу этой замечательной игры на новый движок - Александр Янг.

Pong — первая игра, показавшая, что игры — это серьезно. Забавно, но двух ракеток и шарика-пикселя хватило, чтобы устроить первый бум аркадных автоматов: игровые машины с Pong были так популярны, что рынок вскоре заполонили ее клоны. Впоследствии компания Atari выпустила версию Pong для консоли Atari 2600, доказав, что домашние игровые системы тоже имеют право на жизнь. Успех Pong также стал сигналом для других игровых компаний — например, по горячим следам Konami вошла на аркадный рынок с игрой Maze.

Это руководство призвано помочь разработчикам улучшить производительность в играх, сделанных на Unreal Engine 4 (UE4). Здесь мы расскажем об инструментах, которыми можно пользоваться и в самом движке, и за его пределами, о наилучших подходах в использовании редактора, а также о скриптинге, помогающем увеличить фреймрейт и стабильность проекта.

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

При написании этого руководства использовался UE4 версии 4.14.

Единицы измерения

Для измерения оптимизационных улучшений используются кадры в секунду (эту единицу измерения также называют «фреймрейтом» или «фпс») и миллисекунды на кадр («мс»).

График ниже показывает отношение между средним фреймрейтом и миллисекундами.

Чтобы узнать мс при каком-либо фпс, просто узнаем величину, обратную фпс (т.е. берем 1 и делим ее на фпс), а затем умножаем ее на 1000.

1/ФПС x 1000 = МС

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

Вот пара примеров увеличения фпс на 20 кадров в секунду:

  • Чтобы поднять фпс с 100 до 120, нужно улучшить результат на 1,66 мс
  • Чтобы поднять фпс с 10 до 30, нужно улучшить результат на 66,67 мс

Инструменты

Перед тем, как начать, давайте рассмотрим три инструмента – чтобы понять, что происходит под капотом движка. Это UE4 CPU Profiler, UE4 GPU Visualizer и Intel Graphics Performance Analyzers (Intel GPA).

Profiler

UE4 CPU Profiler – это инструмент, который встроен в UE4 и позволяет отслеживать производительность в игре, будь это игра вживую или просто сохраненный фрагмент.

Чтобы найти Profiler, кликните в UE4 на Window > Developer Tools > Session Frontend.

Как добраться до окна Session Frontend

В Session Frontend выберите вкладку Profiler.

Profiler в Unreal Engine

Теперь, когда вы в окне Profiler, выберите Play-In-Editor (PIE), а затем выберите Data Preview и Live Preview, чтобы увидеть данные, считываемые с игры. Чтобы начать захват данных, нажмите Data Capture, а чтобы сохранить эти данные для дальнейшего просмотра, отожмите Data Capture.

Просмотр процессов через Profiler

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

GPU Visualizer

UE4 GPU Visualizer определяет, сколько вычислительных ресурсов требуется на проходы рендеринга (от «rendering pass»), а также позволяет во всех подробностях просматривать, что происходит в пределах того или иного кадра.

Открыть GPU Visualizer можно через консоль разработчика, вписав туда «ProfileGPU».

Консольная команда ProfileGPU

После того, как вы впишите команду, появится окно GPU Visualizer. В нем демонстрируется, сколько времени занимают проходы, а также примерное расположение этих проходов в сцене.

Просмотр процессов через GPU Visualizer

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

Intel GPA

Intel Graphics Performance Analyzers (Intel GPA) – это набор инструментов для анализа и оптимизации, призванных помочь разработчикам сделать свои графические проекты более производительными.

В этом руководстве мы сфокусируемся на двух аспектах этого набора: Analyze Application и Frame Analyzer. Для начала загрузите GPA с Intel Developer Zone. Установив, скомпилируйте свой проект с настройкой Development (чтобы выбрать ее, кликните на File > Package Project > Build Configuration > Development).

Когда проект скомпилируется, запустите Graphics Monitor, кликните на пункт Analyze Application, выберите нужный файл *.exe в поле Command Line и, нажав на кнопку Run, запустите его.

Далее запустится игра – так же, как запускается обычно, однако в левом верхнем углу теперь будет меню со статистикой. Чтобы расширить его, кликните Ctrl+F1. Если нажать на Ctrl+F1 один раз, появится несколько окошек с показателями, измеряемыми в реальном времени. Если нажать Ctrl+F1 еще раз, появится список команд (плюс горячие клавиши, которые нужно нажать для их выполнения), с помощью которых можно экспериментировать c игрой, пока та будет запущена.

Меню Intel GPA в игре

Чтобы сделать кадр для последующего анализа в Frame Analyzer, нужно зайти в игру и сделать два дополнительных действия.

Сначала включите Toggle Draw Events. Чтобы сделать это, впишите в консоли «ToggleDrawEvents».

Консольная команда ToggleDrawEvents

Когда вы включите эту функцию, командам отрисовки, идущим от движка, будут присвоены названия. Это позволит понимать что к чему, когда вы будете смотреть на захваченный кадр в Frame Analyzer.

Наконец, сохраните кадр, нажав на горячие клавиши Ctrl+Shift+C.

Сохранив кадр, запустите Graphics Monitor, кликните на пункт Graphics Frame Analyzer и выберите кадр, который нужно загрузить. После того, как сохранение будет завершено, программа покажет всю информацию о графике, имеющейся в кадре.

Пример использования Intel GPA

Обилие данных в Intel GPA поначалу кажется сложным, поэтому давайте начнем с самых больших фрагментов информации. В правом верхнем углу окна выставьте обе оси (X и Y) на GPU Duration – в результате получится график того, какие команды отрисовки в этом кадре являются наиболее ресурсоемкими.

В нашем примере, т.е. в кадре с пустынным ландшафтом, видно, что самым ресурсоемким получился базовый проход. Выбрав самый большой пик на графике (то есть, в сущности, самую ресурсоемкую команду отрисовки), а также пункт Highlighted в левом нижнем превью-окне (оно называется Render Target Preview), мы видим, что причиной пика стал ландшафт (он подсвечен розовым цветом).

Далее, перейдя в окно Process Tree List (оно находится выше превью-окна и показывает список процессов), чтобы найти выбранную команду отрисовки, мы видим, что этот ландшафт состоит из 520200 примитивов, а на его обработку у GPU (это и есть показатель GPU Duration) уходит 1,3185 миллисекунд (мс).

Поиск самой ресурсоемкой команды отрисовки в кадре

Теперь, когда мы знаем, что стало причиной пика, можно приступить к оптимизации.

Во-первых, ландшафт можно пересобрать при помощи режима Manage у инструмента UE4 для создания ландшафтов, что позволяет снизить количество примитивов до 129032, а GPU Duration – до 0,8605 мс. Таким образом, сцена оптимизируется на 5%.

Видим уменьшение GPU Duration

Чтобы снова снизить ресурсную «стоимость» ландшафта, давайте взглянем на материалы. Наш ландшафт использует материал с 13 текстурами 4096 x 4096 (4K), и в результате на текстурный стриминг приходится в целом 212,5 Мб.

Просмотр отрендеренных текстур в Intel GPA

Сжав все ландшафтные текстуры до 2048 х 2048 (2K), мы сократили GPU Duration до 0,801 мс и улучшили производительность на дополнительные 6%.

В итоге снижение текстурного стриминга для ландшафта до 53,1 Мб и уменьшение числа примитивов позволили сделать проект более быстрым. И все это ценой лишь очень небольшого снижения визуального качества ландшафта.

Видим снижение GPU Duration, достигнутое благодаря снижению размера текстур

В целом, просто пересобрав сцену и изменив текстуры, мы сумели достичь следующего:

  • Снизили GPU Duration при обработке ландшафта на 40 % (с 1,3185 до 0,801 мс)
  • Улучшили фпс на 18 кадров (с 143 до 161)
  • Снизили мс на 0,7 миллисекунд

Оптимизация в редакторе

Forward Rendering против Deferred Rendering

Deferred Rendering – это стандартный метод рендеринга, используемый в UE4. Использование Deferred Rendering, как правило, улучшает картинку, но и может повлечь проблемы с производительностью, особенно в VR-играх и на слабых машинах. В данных случаях разумнее переключиться на Forward Rendering.

К примеру, в сцене Reflection из магазина Epic можно заметить что между рендерингом методами Deferred и Forward есть некоторые отличия.

Сцена Reflection, отрендеренная методом Deferred

Сцена Reflection, отрендеренная методом Forward

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

Если взглянуть в Intel GPA на кадр из этой сцены, отрендеренной методом Deferred, мы увидим, что сцена работает на 103,6 мс (9 фпс), и значительную часть этого времени занимает обработка освещения и отражений.

Данные о кадре из сцены Reflection, отрендеренной методом Deferred на Intel HD Graphics 530

А если взглянуть на кадр, отрендеренный методом Forward, мы увидим, что показатель «мс» улучшился с 103,6 до 44,0 (т.е. на 259%), а больше всего времени уходит на базовый проход и пост-обработку, над оптимизацией которых тоже можно поработать.

Данные о кадре из сцены Reflection, отрендеренной методом Forward на Intel HD Graphics 530

Уровень детализации

Статические сетки в UE4 могут состоять из тысяч или даже сотен тысяч треугольников – чтобы показать самые мельчайшие детали, которыми 3D-художник украсил свою работу. Однако, когда игрок находится далеко от модели, он этих деталей не видит, а движок эти треугольники по-прежнему обрабатывает. Чтобы решить эту проблему и тем самым оптимизировать игру, мы можем использовать так называемые «уровни детализации» (или просто LOD – от англ. «level of detalization»), чтобы на близком расстоянии эти детали показывались, а на далеком – нет.

Генерация LOD

В стандартном пайплайне LOD’ы создаются 3D-моделлером еще при создании самой модели. Хотя этот метод позволяет контролировать конечный результат, в UE4 встроен отличный инструмент для автоматической генерации LOD’ов.

Автогенерация LOD’ов

Для этого выберите нужную модель, перейдите во вкладку Details, а затем к пункту LOD Settings. Там найдите пункт Number of LODs (т.е. количество уровней детализации) и впишите туда нужное значение.

Автоматическая генерация уровней детализации

Кликните на Apply Changes. Для движка это станет сигналом для генерации нескольких LOD’ов, и оригинальной моделью среди них будет LOD0. В примере ниже показано, что при создании пяти LOD’ов количество треугольников у нашей статической сетки уменьшается с 568 до 28 – это значительное снижение нагрузки на GPU.

Количество треугольников и вершин, а также размер на экране для каждого LOD’а

Если разместить эту модель на сцене, мы увидим, как она будет меняться при удалении от камеры.

Визуальная демонстрация LOD’ов, показанная в зависимости от размера на экране

Материалы для LOD’ов

Еще одна функция LOD’ов – это то, что каждый из них может использовать собственный материал. Это позволяет еще больше снизить «стоимость» статической сетки.

Материалы, присвоенные каждому уровню детализации

К примеру, в игровой индустрии повсеместно используются карты нормалей. Однако в VR-играх возникает проблема – карты нормалей не идеальны, поскольку при ближайшем рассмотрении игрок видит, что это просто плоская поверхность.

Эту проблему можно решить при помощи LOD’ов. Поскольку LOD0 детализирован до такой степени, что на нем видны мелочи вроде болтов и шурупов, когда игрок рассматривает этот объект вблизи, то испытывает более сильный эффект погружения. Поскольку все эти детали смоделированы, на первом LOD’е от карты нормалей можно отказаться. Когда игрок удаляется от этого объекта, движок переключается на другой LOD, на котором как раз стоит карта нормалей, снижающая детализацию модели. Когда игрок удалится еще дальше, карту нормалей можно убрать, потому что она станет слишком маленькой и ее попросту не будет видно.

Статические сетки-экземпляры

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

К примеру, у нас есть две сферы, состоящие из 200 восьмигранных сеток – одна зеленая, а другая синяя.

Сфера из статических сеток и сеток-экземпляров

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

Команды отрисовки для 200 статических сеток (максимум – 569)

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

Команды отрисовки для 200 сеток-экземпляров (максимум – 143)

Если взглянуть на оба примера через GPU Visualizer, то базовый проход для зеленой (со статическими сетками) сферы занимает 4,30 мс, а для синей (с сетками-экземплярами) – 3,11 мс. Таким образом, мы оптимизируем сцену на 27%.

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

Если большинство сеток-экземпляров находится за кадром, они по-прежнему рендерятся

Иерархические статические сетки-экземпляры

Если вы используете статические сетки с LOD’ами, обратите внимание на иерархические сетки-экземпляры.

Сфера из иерархических сеток-экземпляров с LOD’ами

Как и стандартные сетки-экземпляры, иерархические сетки-экземпляры снижают количество команд отрисовки, но также используют информацию о LOD’ах.

Сфера из иерархических сеток-экземпляров с LOD’ами; вид вблизи

Occlusion Culling

В движке UE4 функция Occlusion Culling – это система, позволяющая сделать так, чтобы объекты, которые игрок не видит, не рендерились. Это позволяет снизить системные требования к игре, поскольку движку больше не приходится рисовать абсолютно все объекты абсолютно во всех сценах и абсолютно во все кадрах.

Восьмиугольники, разбросанные по сцене

Чтобы видеть загороженные объекты (они будут показаны прозрачными кубами с зелеными краями), в консоли редактора введите «r.VisualizeOccludedPrimitives 1». Чтобы выключить эту настройку, вместо «1» впишите «0».

Края загороженных сеток; эти края стали видны после использования команды r.VisualizeOccludedPrimitives 1

То, будет сетка рендериться или нет, зависит от так называемого «граничного куба» (от англ. «bounding box»). Благодаря ему некоторые объекты могут быть невидимы для игрока, но видны для камеры – в таком случае движок принимает решение рендерить эти объекты.

Просмотр границ объекта в окне для работы с объектом

Если сетку нужно отрендерить до того, как ее увидит игрок – например, для рендеринга анимации бездействия (от англ. «idle animation», это анимация персонажа, которая активируется, когда он стоит на месте и ничего не делает; это может быть чесание затылка, ковыряние ногой в земле и т.д.) – то размер граничного куба можно увеличить. Это можно сделать в окне для работы с объектом, в меню Static Mesh Settings. Ищите там пункты Positive Bounds Extension и Negative Bounds Extension.

Задаем масштаб для границ объекта

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

Давайте представим мысленный эксперимент, где мы создаем 3D-модель, а затем экспортируем ее в UE4. Как нам подойти к созданию арены в стиле Колизея?

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

Но, во-первых, мы должны отказаться от идеи того, что вся арена должна быть одним большим цельным объектом. В этом случае количество треугольников, которые нужно будет отрендерить, будет соответствовать размеру всей арены – независимо от того, смотрим ли мы на ее отдельные части или нет. Как нам оптимизировать эту модель?

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

Вариант первый – «нарезанная пицца». То есть мы создаем 8 идентичных острых кусочков, «носы» которых направлены в центр арены. Этот метод прост, но для Occlusion Culling он подходит не очень, поскольку в этом случае будет много перехлестов между граничными кубами. Если игрок будет стоять в центре и смотреть вокруг, его камера будет захватывать 3-4 куба, т.е. большую часть времени движку придется рендерить половину арены. В самом худшем случае игрок может стать спиной к стене, посмотреть на арену вокруг него и тем самым захватить в кадр все 8 кусочков «пиццы». Оптимизации никакой.

Вариант второй – «крестики-нолики». Здесь мы создаем 9 кусочков. Это не самый традиционный метод, но его преимущество в том, что здесь нет перехлестов между граничными кубами. Как и в случае с «пиццей», если игрок будет стоять в центре арены, то захватит в кадр 3-4 кусочка. Однако, став спиной к стене, он захватит в кадр 6 из 9 кусочков, что по сравнению с «пиццей» дает некоторую оптимизацию.

Последний вариант – «нарезанное яблоко» (1 центральный кусочек и 8 боковых). Это самый распространенный метод для этого мысленного эксперимента, и очень неплохой – перехлест между граничными кубами есть, но небольшой. Если игрок будет стоять в центре арены, то захватит в кадр 5-6 кусочков, но в отличие от первых двух вариантов, в самом худшем случае (вплотную спиной к стене) будут рендериться те же 5-6 кусочков.

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

Каскадные карты теней

Хотя каскады динамических теней (от англ. «dynamic shadow cascade») добавляют вашей игре высокий уровень детализации, они могут оказаться очень «дорогостоящими» в плане производительности – чтобы играть в такую игру без потери фреймрейта, понадобится мощный PC.

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

«Стоимость» каскадов динамических теней на Intel Graphics 350

Значением в каскадах динамических теней можно управлять динамически. Это можно сделать несколькими способами:

  • Поменяв качество теней в настройке Settings > Engine Scalability Settings > Shadows
  • Отредактировав параметры в файле «BaseScalability.ini»: в настройках Shadow.CSM.MaxCascades (между «0» и «4») и sg.ShadowQuality (между «0» и «3» – для «низкий», «средний», «высокий» и «эпический»)
  • Добавив нод Execute Console Command в блюпринт игры, где вы вручную поменяли параметр Shadow.CSM.MaxCascades

Оптимизация через скриптинг

Отключение полностью прозрачных объектов

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

Чтобы сделать это при помощи блюпринтов, в UE4 нужно задействовать несколько разных систем.

Набор параметров для материалов

Во-первых, создаем набор параметров для материалов (или просто MPC – от англ. «material parameter collection»). Здесь будут храниться линейные и векторные параметры, которые можно будет привязать к любому материалу в игре. Их можно использовать для модификации этих материалов прямо во время игры – для создания динамических эффектов.

Создаем MPC, кликая на вкладке Content Browser по Add New > Materials & Textures > Material Parameter Collection.

Создание MPC

Будучи в MPC, мы можем создать, назвать и задать дефолтные значения для линейных и векторных параметров. В нашем случае понадобится линейный параметр – мы назовем его Opacity (т.е. «прозрачность») и с его помощью будем управлять прозрачностью нашего материала.

Задаем линейный параметр под названием Opacity

Материал

Поиск нода Collection Parameter в материале

Создав нод, соединяем его с параметром Opacity на базовом материале.

Настраиваем Collection Parameter в материале

Скрипт в блюпринте

Создав MPC и материал, заходим в блюпринт и настраиваем его так, чтобы можно было задавать и считывать значения с MPC. Это делается при помощи нодов Get/Set Scalar Parameter Value и Get/Set Vector Parameter Value. Далее заходим в эти ноды, в пункте Collection выбираем набор, который хотим использовать (MPC), а в пункте Parameter Name – название параметра из этого набора.

Для этого примера мы делаем так, чтобы линейное значение Opacity было синусом ко времени игры – чтобы видеть значения в диапазоне от «1» до «-1».

Задаем и считываем линейный параметр, а также используем его значение в функции

Чтобы определять, рендерится объект или нет, создаем новую функцию под названием Set Visible Opacity. Входными значениями у нее будут параметр Opacity из MPC и статическая сетка, а выходным – значение типа Boolean, сообщающее о том, виден ли объект или нет.

Далее мы запускаем проверку на то, чтобы значение было чуть больше «0» (в данном случае, больше «0,05»). Проверка на «0» может сработать, но при приближении к «0» игрок больше не сможет видеть объект, поэтому мы можем просто выключить его до того, когда значение станет «0». Кроме того, это позволяет создать буфер – на случай ошибок с плавающей точкой, из-за которых линейный параметр не сможет получить точный «0». К примеру, если значением будет «0,0001», эта система его просто выключит.

Далее создаем нод Branch – если на выходе у него будет True, то и видимости объекта (верхний нод Set Visibility) будет дано значение «true», а если False, то видимости объекта (нижний нод Set Visibility) будет дано «false».

Функция Set Visible Opacity

Нод Event Tick, время и проверка на рендер

Если в блюпринте сцены используется нод Event Tick, эти скрипты будут работать, даже если объектов на экране не видно. Как правило, в этом нет ничего страшного, но чем меньше блюпринтов «тикает» в течение каждого кадра, тем шустрее эта сцена бегает.

Вот несколько ситуаций, когда можно использовать этот тип оптимизации:

  • Вещи, которым необязательно работать, когда игрок на них не смотрит
  • Процессы, которые выполняются в зависимости от игрового времени
  • Неигровые персонажи (NPC), которым необязательно что-то делать, когда рядом нет игрока

В качестве самого простого решения перед Event Tick можно поставить нод Was Recently Rendered. Таким образом, для того, чтобы наш Event Tick включался/выключался, нам не нужно подключать к нему специальные события и детекторы. Кроме того, эта система по-прежнему может быть независима от других процессов, происходящих в сцене.

Управление нодом Event Tick с помощью проверки на рендер

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

Значение Emissive Value в Material Collection задано таким образом, что во время рендера оно будет работать как абсолютная синусоида игрового времени

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

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

Это работает и с остатком целочисленного деления, но в этом случае граф выглядит по-другому.

Проверку на рендер при помощи нода Was Recently Rendered можно сделать и чуть позже. То есть, если у объекта, которым управляет нод Event Tick, есть какие-то задачи, которые нужно выполнять каждый кадр, но можно сделать так, чтобы эти задачи выполнялись и до проверки на рендер (см. граф ниже). Чем меньше нодов будет вызываться с каждым «тиком» нода Event Tick, тем лучше.

Использование проверки на рендер для управления визуальными фрагментами блюпринта

Еще один способ снизить «стоимость» блюпринта – это замедлить его и позволить ноду Event Tick «тикать» только один раз в течение определенного интервала. Этот интервал задается при помощи нода Set Actor Tick Interval.

Переключение между интервалами

Кроме того, интервал, с которым «тикает» нод Event Tick, можно задать в пункте Tick Interval – он находится во вкладке Details у блюпринта, над которым вы работаете. Здесь интервал задается в секундах.

Пункт Tick Interval во вкладке Details

Это удобно, к примеру, когда нужно сделать счетчик, срабатывающий каждую секунду.

Создаем параллельный счетчик, срабатывающий каждую секунду

В качестве примера того, как этот тип оптимизации может снизить средний показатель мс, давайте взглянем на граф ниже:

Невероятно полезный пример того, как делать не нужно

Здесь у нас нод ForLoop, который считает от «0» до «10000», и для него через нод SET задано целое число Count. Этот граф очень ресурсоемок и неэффективен – настолько, что показатель мс у нашей сцены составляет целых 53,49 мс.

Просмотр в Stat Unit «стоимости» невероятно полезного примера

Перейдя в Profiler, мы понимаем почему. Этот простой, но крайне неэффективный блюпринт за каждый тик «поедает» 43 мс.

Просмотр в Profiler фрагмента, отвечающего за срабатывание Event Tick в каждом кадре

Но если заставить этот блюпринт «тикать» каждую секунду, то большую часть времени он будет «поедать» 0 мс. Если посмотреть на среднее время (выделите какой-нибудь фрагмент таймлайна в окне Graph View) за три «тика», мы увидим, что средний показатель составляет 0,716 мс.

Просмотр в Profiler фрагмента, отвечающего за срабатывание Event Tick каждую секунду

Или возьмем более распространенный случай: допустим, у нашего блюпринта 1,4 мс, и если сцена будет работать на 60 фпс, то на обработку этого блюпринта будет уходить 84 мс. Но если уменьшить время, в течение которого у блюпринта «тикает» нод Event Tick, то это снизит и общее время, затрачиваемое на обработку этого блюпринта.

Массовое движение, нод ForLoop и многопоточность

Когда несколько моделей движутся одновременно, это выглядит очень здорово и может сделать визуальный стиль очень привлекательным. Правда, в таком случае на CPU ложится большая нагрузка, из-за чего в конечном счете страдает и фпс. Впрочем, это тоже можно оптимизировать, разбив массовое движение на несколько блюпринтов – благодаря многопоточности и умению UE4 управлять рабочими потоками.

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

Ниже – простой скрипт, создающий решетку. Просто добавляем компонент Instanced Static Mesh, во вкладке Details выбираем сетку, которую будем использовать, а затем добавляем следующие ноды:

Скрипт для создания простой решетки

Создав решетку, добавляем этот скрипт во вкладку Event Graph.

Пару слов о ноде Update Instance Transform. Если какой-либо из экземпляров будет трансформирован, это изменение не будет показано, пока пункт Mark Render State Dirty не будет помечен как «true». Но это ресурсоемкая операция, т.к. проверка идет через каждую сетку. Чтобы сэкономить вычислительные ресурсы, особенно если этот нод запускается по несколько раз за «тик», можно сделать так, чтобы сетки обновлялись в конце блюпринта. В скрипте ниже пункт Mark Render State Dirty помечается как «true» только при соблюдении двух условий – если на ноде ForLoop стоит Last Index и если значение в Index соответствует Grid Size минус 1.

Блюпринт с динамическим движением для статических сеток-экземпляров

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

Несколько вариантов решетки с 1600 сетками

Запустив сцену, мы увидим элементы решетки, плавающие вверх и вниз.

Решетка из 1600 статических сеток-экземпляров, динамически двигающихся вверх и вниз

Тем не менее, тип разбиения на фрагменты влияет на скорость, с которой работает сцена.

Во-первых, если решетка будет состоять из 1600 отдельных фрагментов, то все 1600 блюпринтов будут обработаны за 16,86 мс (т.е. в среднем 0,0105 мс на один блюпринт). То есть, хотя «цена» одного блюпринта невелика, их суммарное количество замедляет систему. Единственная вещь, которую здесь можно сделать – это уменьшить количество блюпринтов, срабатывающих с каждым «тиком». Другая причина большой нагрузки заключается в большом количестве отдельных сеток, из-за чего увеличивается количество и команд отрисовки, и команд для трансформации сетки.

Во-вторых, если решетка будет состоять из одного фрагмента, в который входит 1600 сеток, то этот вариант будет очень хорошо оптимизирован в плане команд отрисовки (потому что на всю решетку потребуется только одна команда отрисовки), но «стоимость» блюпринта, которому за один «тик» нужно будет обработать 1600 сеток, составит 19,63 мс.

Но если разбить решетку по-другому (на 4 фрагмента на 400 сеток, на 64 по 25 или на 16 по 100), то результат получается более оптимизированным – благодаря уменьшенному времени обработки скрипта и умению UE4 работать с многопоточностью. Благодаря последней UE4 может распределять нагрузку по обработке блюпринтов по нескольким рабочим потокам, тем самым эффективно используя все ядра CPU.

Если мы посмотрим на время обработки блюпринтов и то, как они распределяются по рабочим потокам, то увидим следующее:

Структуры данных

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

Пример использования

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

Самый распространенный метод использования объектного пула – это взять первую, пока еще не включенную пулю в массиве/списке, переместить ее в стартовую позицию, включить ее, а затем выключить, когда она вылетит за экран или попадет во врага. Проблема этого метода во времени, которое требуется на работу скрипта, т.е. в большом «О» . Поскольку вы делаете много циклов, проверяя объекты и ища, какой из них нужно выключить, при использовании 5000 объектов на поиск одного объекта может уйти очень много циклов. У этого метода время будет представлено в виде O(n), где «n» – это количество объектов в наборе.

Хотя O(n) – это далеко не худший алгоритм. Чем ближе мы будем к O(1) – т.е. к фиксированной «стоимости», независящей от размера – тем более эффективным будет скрипт и более шустрой будет игра. Чтобы провернуть этот прием вместе с объектным пулом, мы используем структуру данных, именуемую «очередью». Как и в настоящей очереди, эта структура данных берет первый объект в наборе, использует его, а затем удаляет – и так до тех пор, пока не использует все объекты в очереди.

Используя эту «очередь» для нашего объектного пула, мы можем взять передний фрагмент набора, включить его, затем убрать и сразу же поместить его в заднюю часть набора. Это создаст в скрипте эффективный цикл и уменьшит время работы скрипта до O(1). Мы также можем добавить к этому циклу проверку – если удаленный объект был включен, то скрипт берет его и, не создавая новый объект, помещает в конец очереди, увеличивая размер набора, но не увеличивая времени обработки скрипта.

Очереди

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

  • Удаление

Реализация конструкции queue::pop в блюпринте UE4; удаляет элемент с переднего конца очереди

  • Добавление

Реализация конструкции queue::push в блюпринте UE4; вставляет новый элемент в конец очереди

  • Определение того, пуста ли очередь
  • Определение размера очереди

Реализация конструкции queue::size в блюпринте UE4; сообщает размер очереди

  • Возвращение указателя на первый элемент в очереди

Реализация конструкции queue::front в блюпринте UE4; возвращает указатель на первый элемент в очереди

  • Возвращение указателя на последний элемент в очереди

Реализация конструкции queue::back в блюпринте UE4; возвращает указатель на последний элемент в очереди

  • Вставка элемента в определенное место очереди

Вставляет указанный элемент в указанное место очереди (с проверкой позиции)

  • Обмен данными

Реализация конструкции queue::swap в блюпринте UE4; заставляет два контейнера обменяться данными (с проверкой позиции)

Стеки

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

  • Удаление

Реализация конструкции stack::pop в блюпринте UE4; удаляет элемент с переднего конца стека

  • Добавление

Реализация конструкции stack::push в блюпринте UE4; вставляет новый элемент в конец стека

  • Определение того, пуст ли стек

Реализация конструкции stack::empty в блюпринте UE4; сообщает, пуст ли стек

  • Определение размера стека

Реализация конструкции stack::size в блюпринте UE4; сообщает размер стека

  • Возвращение указателя на последний элемент в стеке

Возвращает указатель на последний элемент в стеке

  • Вставка элемента в определенное место стека

Вставляет указанный элемент в указанное место стека (с проверкой позиции)

Движок Unreal Engine берёт свои корни ещё в далеком 1998 году. С тех пор было создано немало потрясающих игр. В этой статье мы расскажем про 7 лучших из них. На момент создания движка он использовался для создания простых игр с 2D видом . Постепенно начали появляться более современные 3D экшен игры. Популярность движка обеспечивала уникальная система работы, он имеет одновременно: графическое, физическое ядро, встроенный искусственный интеллект, а также инструменты для управления системами файлов сетями. Главная достопримечательность заключалась в наличии готовой среды для создания игр – UnrealEd .

#7 - Batman: Arkham Knight

Данная игра имеет жанр экшен боевика. В основе сюжета лежат события, которые произошли спустя 9 месяцев после известной войны в Аркхем Сити. Так как Джокер мёртв, Готэм начинает возвращаться в привычную колею жизни, наступает более безопасное время для жителей, но равновесие сил пропадает, когда в очередной день жители Готэма бросаются друг на друга в кафе без видимой причины.

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


Главный герой – Бэтмен , который неустанно сражается за безопасность родного города и искореняет преступность. В процессе игры будут появляться многочисленные враги, красивые локации, уникальные персонажи. Игра отличается внимательным подходом к геймплею и поэтому достойна занимать 7 позицию среди лучших.

#6 - Street Fighter V

Есть игры, которые без преувеличения известны во всём мире, Street Fighter – это одна из таких игр. Современная пятая часть заполнит образовавшуюся пустоту в связи с нелогичным выходом третьей и шестой части. Для тех немногих, кто ещё не знаком с игрой – это файтинг, где пользователь сражается с врагами. Основа популярности заключается в возможности мультиплеера, а игра с другом всегда приносит «живые» эмоции.


Известность у игры ещё с незапамятных времён, она обусловлена множеством персонажей с уникальными характеристиками и боевыми способностями. Ранее были персонажи и пользователи высокого класса, что выиграть у них невозможно, но постепенно боевая стратегия и приёмы изменились и приобрели больший баланс.

#5 - We Happy Few

В центре внимания игры 1964 год , когда в городе под названием Веллингтон-Уэллс (наименование вымышлено) были разработаны препараты для увеличения радости, она так и называется - сыворотка «Радость». В её основе лежит очищение воспоминаний. Всё дело в том, что во время Второй Мировой Войны жители прибегли к использованию крайне плохих вещей, что спровоцировали сильное подавление духа нации. Сыворотка призвана устранить эти воспоминания и сделать людей более счастливыми, при чем насильно. Те жители, что отказываются употреблять «Радость» называются «Зануды» и они искореняются.


Главный герой – Артур Гастингс , обычный клерк, который занимается наложением цензуры на газеты «несчастливых» новостей из прошлого. Перебирая архивы газет, он обнаруживает своё фото и младшего брата на обложке. В его голову прокрадываются воспоминания, и они приносят боль. С целью узнать самого себя он отказывается пить «Радость». После окончания эффекта коллеги различают в нём «Зануду» и начинают преследовать. Это заставляет Артура бежать в подземелья.

#4 - Gears of War 4

Культовая серия игр снова вдохновляет пользователя погрузиться в мир «мессива» . В отношении геймплея значительных отличий от предыдущих частей не наблюдается. Игра так и осталась отличным шутером, где присутствуют многочисленные враги и укрытия. Оружия действительно много, вплоть до автомата с бензопилой в роли подствольного штыка. Сражения происходят как с Ордой, они хоть и жуткие, но живые, так и роботами КОГ. Все монстры стремятся поглотить героя.


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

#3 - Mortal Kombat X

Mortal Kombat входит в тройку лучших игр на движке Unreal Engine . Она имеет жанр файтинг, который рассматривался ранее на примере Street Fighter V . Здесь присутствует множество персонажей, несметное количество ударов, но их сделать бывает достаточно сложно, так как комбинации длинные и должны выполняться точно. В основе популярности игры лежит великолепный геймплей, зрелищные бои и красивые модели персонажей, местности для драк.


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

#2 - BioShock Infinite

BioShock – это интереснейший шутер, который завораживает своей атмосферой и имеет некоторые элементы RPG , то есть можно прокачивать способности персонажа. Игра переносит пользователя в далекий 1912 год , действия происходят в парящем городе Колумбия.


Пользователю предстоит играть за детектива частной практики Букера Девитта, который попадает в город для поиска Элизабет. После обнаружения девушки оба героя становятся заключенными войны между властями и мятежниками, простым, рабочим классом.

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

#1 - Dishonored

Стелс-экшен сегодня становится достаточно популярным жанром, но соревноваться с Dishonored сложно. Дополнительно в игре присутствуют элементы жанра RPG.

Игра переносит в город, который полностью погряз в эпидемии чумы – это Дануолл. Заметно, что город во многом напоминает Лондон древних лет, приблизительно Викторианской эпохи. Главный герой – Корво Аттано желает восстановить справедливость, ведь на него повесили вину в убийстве императрицы. Из тюремного заключения лорд убегает и пытается наладить равновесие добрых и злых сил.

Корво не пренебрегает никакими способами решения ситуации, поэтому «подрабатывает» наёмным убийцей. Основная задача заключается в поиске и устранении определенного персонажа. В игре присутствует большое количество различного оружия, но и это ещё не всё, ведь персонаж обладает уникальными способностями.


В игре присутствует интересный сюжет, он отличается нелинейностью. Практически каждая миссия может быть выполнена множеством способов, в частности – можно наделать шума и убивать многочисленных противников или убить врага скрытно, чтобы никто не заметил.



Приветствую, Хабр! Хотел бы познакомить вас с относительно небольшим проектом, который я сделал c нуля примерно за 150 часов (50 заходов ~3 часа каждый) на Unreal Engine 4. Проект я делал в прямом эфире только на стримах раз в неделю (в общей сложности ушел год), попутно отвечая на вопросы пользователей.

Сам проект не предназначался как коммерческий. Целью я ставил на практике показать всю сложность разработки игр, а именно такие проблемы, как:

  • Планирование и прототипирование проекта
  • Продумывание и реализация архитектуры проекта и отдельных его компонентов
  • Реализация интерфейса пользователя
  • Отладка и исправление ошибок
  • Работа с ассетами и графикой

В конце всей серии стримов у нас получился играбельный прототип “Сурвайвл” шутера. Те, у кого стакан наполовину полон, смогут даже назвать это пре-альфой без сюжета.

Если вам интересны подробности проекта, записи стримов, исходники и прочее, читайте далее.

Весь проект был реализован на визуальной системе программирования, под названием “Блупринты”. И конечно многие спецы могут назвать её ребяческой, разработать на ней можно спокойно даже относительно крупный проект. Более того, это можно сделать относительно быстро, как мы уже смогли доказать.

Сразу хочу ответить на вопрос: "Почему Блупринты, а не С++? ". Ну во первых, когда я начинал серию, плюсы я почти не знал. Хотя я и сейчас подобный сингл делал бы на БП. Во вторых, БП почти не уступают плюсам в нашем случае, но при этом дают ряд возможностей: Не позволяют наделать множество ошибок, возможных с плюсами, не приходится отвлекаться между БП и С++, понятнее новичкам. Да и они в нашем случае не намного медленнее, учитывая тот факт, что почти вся логика построена на событиях.

Мы так же успели немного поработать над графикой. К сожалению, ассеты делать времени у нас не было, поэтому мы часть оставили пустышками, часть сделали прямо в редакторе из примитивов, а некоторый контент позаимствовали из бесплатных демок Epic Games. Тем не менее, что-то успели сделать и сами, например систему дня и ночи, постобработку для воды и некоторые материалы объектов сцены.

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

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

Список всего, что мы успели реализовать в нашей игре

Персонаж

  • Управление персонажем
  • Система жизненных показателей (Жизни, броня, стамина, голод, жажда)
  • Переключение вида (от первого лица и от третьего)
  • Моделька (сделали во Fuse, анимации взяли с Mixamo)
  • Настроенные анимации передвижения и использования оружия
  • Универсальное взаимодействие с предметами

Объектная система инвентаря

  • Компонент инвентаря (встраивай в любой объект, куда хочешь)
  • Клеточная система с поддержкой различного размера предметов
  • Размер инвентаря по клеткам на страницу и по весу.
  • Класс предметов, которые можно положить в инвентарь. Предметы хранятся в качестве объектов.
    • Вес, размер, информация, состояние предмета
    • Функционал для стака (когда в одной ячейке много одного предмета)
    • Возможность добавить логику использования предмета
    • Выбрасывание из инвентаря
  • Интерфейс для взаимодействия с инвентарем
  • Интерфейс для обмена между другим компонентом и своим.
  • Drag&Drop манипуляция объектами между инвентарями и внутри одного.
  • Контекстное менюу предметов
  • Подсказки при наведении на предметы в инвентаре и в мире.
  • Список генерируемых предметов при создании объекта с компонентом / начале игры.
  • Список начальных предметов при создании объекта с компонентом / начале игры.
  • Система торговли между другим инвентарем
    • Интерфейс торговли
    • Компонент менеджмента денег (необходим для работы торговли)

Система экипировки

  • Экипировка нескольких типов предметов: Шляпы, Топ, Брюки, Ботинки, Оружие
  • Скелетная синхронизация у Топа, брюк и ботинок. (Шляпы и оружие по сокетам)
  • Удобное окошко для экипировки с поддержкой Drag&Drop
  • Поддержка логики-модификаторов при одевании
Оружие
  • Дальнобойное оружие
    • Перезарядка
    • Использование предметов-патронов из инвентаря
    • Поддержка классов снарядов/пуль
    • Автоогонь/одиночный огонь
    • Отдача с разбросом (свой + от факторов, н.п. бег или приседание)
  • Холодное оружие (с несколькими видами проверок на урон на выбор)
  • Состояние оружия ухудшается при использовании
Система крафта
  • Крафт по рецепту (выбрал рецепт, он скрафтил, аля фоллаут)
  • Крафт по предметам (закинул нужные предметы, он скрафтил, аля майнкрафт)
  • Интерфейс пользователя только для второго типа крафта.
Агрессивные мобы
  • Мобы ближнего боя (если увидят, побегут и начнут бить)
  • Мобы смешанного типа (стреляют, но если достаточно близко, побегут что бы ударить)
  • Дальники оббегают препятствия, если не могут выстрелить.
  • Есть встроенный инвентарь для лута после убийства.
  • Зона спауна
  • Список классов
  • Шанс спауна
NPC
  • Городские NPC, патрулирующие свою зону спауна
  • Уникальные NPC
  • Базовый контроллер расписания для уникальных НПЦ
  • Реакция на урон (убегают или используют имеющееся оружие)
  • Встроенный инвентарь для лута после убийства.
  • Объектная диалоговая система
    • Дерево диалогов
    • Каждый ответ - объект
    • Для каждого ответа можно докинуть любую логику или условие доступности.
    • Интерфейс диалога
    • Несколько готовых классов ответа (запускает торговлю, забирает ресурсы, если есть, выходит из диалога)
Строительство
  • Класс конструкций, которые поддерживают размещение
  • Использование предметов-ресурсов из инвентаря при размещении.
  • Снаппинг на некоторых типах конструкций (н.п. Стены, фундамент, окна)
  • Менюшка с конструкциями
  • Подсвечивание конструкций, на которые хватает ресурсов
Дополнительно
  • Небольшая карта с городом, лесом, водоемами (можно плавать).
  • Система смены дня/ночи
  • Автомобили
    • Вид от первого или третьего. Общее с персом
    • Включение/выключение фар.
    • Встроенный компонент инвентаря (нужно взаимодействовать у багажника)
  • Кое как работающие лестницы вертикального типа.
  • Главное меню
  • Меню паузы
  • Меню с настройками графики

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

Содержание по частям

  1. Начинаем и планируем проект. Создаем управление и поведение персонажа.
  2. Начинаем делать систему инвентаря.
  3. Продолжаем делать базу системы инвентаря.
  4. Готовим базу для экипировки и вооружения.
  5. Работа над оружием и использовании патронов.
  6. Делаем автострельбу и прицеливание.
  7. Создаем базовую систему крафта.
  8. Бег, переработка предметов и их износ.
  9. Реализовываем перезарядку для оружия.
  10. Делаем оружие ближнего боя.
  11. Доделываем ближний бой и делаем лестницу по которой можно взбираться.
  12. Делаем интерактивные предметы: Дерево, камень, кусты.
  13. Делаем HUD и начинаем делать интерфейс для инвентаря.
  14. Продолжаем работать над интерфейсом инвентаря. Делаем генерацию ячеек с предметами.
  15. Продолжаем делать генерацию ячеек и поиск места для предмета. Добавляем страницы инвентаря.
  16. Делаем небольшое взаимодействие с предметами в инвентаре и окно подробной информации.
  17. Сделали Drag&Drop перетаскивание предметов по инвентарю и в другой инвентарь.
  18. В этой части речь идет о визуализации крафта.
  19. Создаем окно с выбором количества предметов из стака для переброса в другой инвентарь.
  20. Делаем поддержку разных рецептов крафта, а так же фиксим разные баги у инвентаря.
  21. Создаем систему смены дня и ночи, а так же делаем новую сцену для нашего проекта.
  22. Начинаем создавать AI для агрессивных ботов.
  23. Делаем атаку мобов, а так же реакцию на атаку. Плюс реализуем сбор лута с мертвых мобов.
  24. Делаем зону спауна для нпц. Так же добавляем генерацию случайных предметов в инвентаре.
  25. Обновляемся до 4.13, а так же делаем дальних агрессивных нпц.
  26. Добавляем разные элементы на HUD. Добавляем ручную перезарядку оружия.
  27. Доделываем поддержку скелетной одежды и шапок. Добавляем анимацию для оружия от первого лица.
  28. Делаем интерфейс для работы с нашей системой экипировки.
  29. Начинаем делать торговую систему и компонент менеджмента денег.
  30. Продолжаем делать торговлю, создавая и настраивая компонент торговли.
  31. Делаем отмену торговли, а так же настраиваем анимацию перезарядки.
  32. Создаем транспорт со своим инвентарем, фарами и переключением вида. Создаем фонарик.
  33. Создаем строительство (а точнее систему размещения объектов перед собой).
  34. Делаем интерфейс для строительства, делаем привязку для стен.
  35. Создаем ещё несколько видов конструкций: Палатка, кровать, стул, стол, лампа, дверь. сундук, костер.
  36. Добавляем крышу, окна. Доделываем выравнивание относительно других конструкций.
  37. Делаем небольшое поселение, а так же населяем его NPC, которые так же создаем в этом уроке.
  38. Начинаем делать систему диалогов для наших жителей.
  39. Настраиваем туман и постобработку. Импортируем модель зомби и настраиваем ему анимации.
  40. Доделываем систему диалогов.
  41. Делаем взаимодействие с предметами от третьего лица, а так же модификаторы для брони.
  42. Создаем главное меню, меню паузы и настройки графики. А так же собираем первую сборку игры.
  43. Реализуем расписание для уникальных жителей.А так же что бы городские NPC убегали от атаки.
  44. Добавляем контекстное меню в инвентарь, а так же фиксим некоторые баги нашего инвентаря.
  45. Добавляем отдачу, разброс, анимацию выстрела и возможность ударить для огнестрельного оружия.
  46. Доделаем агрессивных и городских NPC, фиксим разные баги, связанные с ними.
  47. Настраиваем анимации для главного персонажа. Добавляем различную одежду.
  48. Исправляем различные ошибки в нашей игре.
  49. Исправляем различные ошибки крафта, NPC и экипировки в нашей игре.
  50. Немного дорабатываем карту и собираем последний билд.
  • Разработка игр
  • Приветствую, Хабр! Хотел бы познакомить вас с относительно небольшим проектом, который я сделал c нуля примерно за 150 часов (50 заходов ~3 часа каждый) на Unreal Engine 4. Проект я делал в прямом эфире только на стримах раз в неделю (в общей сложности ушел год), попутно отвечая на вопросы пользователей.

    Сам проект не предназначался как коммерческий. Целью я ставил на практике показать всю сложность разработки игр, а именно такие проблемы, как:

    • Планирование и прототипирование проекта
    • Продумывание и реализация архитектуры проекта и отдельных его компонентов
    • Реализация интерфейса пользователя
    • Отладка и исправление ошибок
    • Работа с ассетами и графикой

    В конце всей серии стримов у нас получился играбельный прототип “Сурвайвл” шутера. Те, у кого стакан наполовину полон, смогут даже назвать это пре-альфой без сюжета.

    Если вам интересны подробности проекта, записи стримов, исходники и прочее, читайте далее.

    Весь проект был реализован на визуальной системе программирования, под названием “Блупринты”. И конечно многие спецы могут назвать её ребяческой, разработать на ней можно спокойно даже относительно крупный проект. Более того, это можно сделать относительно быстро, как мы уже смогли доказать.

    Сразу хочу ответить на вопрос: "Почему Блупринты, а не С++? ". Ну во первых, когда я начинал серию, плюсы я почти не знал. Хотя я и сейчас подобный сингл делал бы на БП. Во вторых, БП почти не уступают плюсам в нашем случае, но при этом дают ряд возможностей: Не позволяют наделать множество ошибок, возможных с плюсами, не приходится отвлекаться между БП и С++, понятнее новичкам. Да и они в нашем случае не намного медленнее, учитывая тот факт, что почти вся логика построена на событиях.

    Мы так же успели немного поработать над графикой. К сожалению, ассеты делать времени у нас не было, поэтому мы часть оставили пустышками, часть сделали прямо в редакторе из примитивов, а некоторый контент позаимствовали из бесплатных демок Epic Games. Тем не менее, что-то успели сделать и сами, например систему дня и ночи, постобработку для воды и некоторые материалы объектов сцены.

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

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

    Список всего, что мы успели реализовать в нашей игре

    Персонаж

    • Управление персонажем
    • Система жизненных показателей (Жизни, броня, стамина, голод, жажда)
    • Переключение вида (от первого лица и от третьего)
    • Моделька (сделали во Fuse, анимации взяли с Mixamo)
    • Настроенные анимации передвижения и использования оружия
    • Универсальное взаимодействие с предметами

    Объектная система инвентаря

    • Компонент инвентаря (встраивай в любой объект, куда хочешь)
    • Клеточная система с поддержкой различного размера предметов
    • Размер инвентаря по клеткам на страницу и по весу.
    • Класс предметов, которые можно положить в инвентарь. Предметы хранятся в качестве объектов.
      • Вес, размер, информация, состояние предмета
      • Функционал для стака (когда в одной ячейке много одного предмета)
      • Возможность добавить логику использования предмета
      • Выбрасывание из инвентаря
    • Интерфейс для взаимодействия с инвентарем
    • Интерфейс для обмена между другим компонентом и своим.
    • Drag&Drop манипуляция объектами между инвентарями и внутри одного.
    • Контекстное менюу предметов
    • Подсказки при наведении на предметы в инвентаре и в мире.
    • Список генерируемых предметов при создании объекта с компонентом / начале игры.
    • Список начальных предметов при создании объекта с компонентом / начале игры.
    • Система торговли между другим инвентарем
      • Интерфейс торговли
      • Компонент менеджмента денег (необходим для работы торговли)

    Система экипировки

    • Экипировка нескольких типов предметов: Шляпы, Топ, Брюки, Ботинки, Оружие
    • Скелетная синхронизация у Топа, брюк и ботинок. (Шляпы и оружие по сокетам)
    • Удобное окошко для экипировки с поддержкой Drag&Drop
    • Поддержка логики-модификаторов при одевании
    Оружие
    • Дальнобойное оружие
      • Перезарядка
      • Использование предметов-патронов из инвентаря
      • Поддержка классов снарядов/пуль
      • Автоогонь/одиночный огонь
      • Отдача с разбросом (свой + от факторов, н.п. бег или приседание)
    • Холодное оружие (с несколькими видами проверок на урон на выбор)
    • Состояние оружия ухудшается при использовании
    Система крафта
    • Крафт по рецепту (выбрал рецепт, он скрафтил, аля фоллаут)
    • Крафт по предметам (закинул нужные предметы, он скрафтил, аля майнкрафт)
    • Интерфейс пользователя только для второго типа крафта.
    Агрессивные мобы
    • Мобы ближнего боя (если увидят, побегут и начнут бить)
    • Мобы смешанного типа (стреляют, но если достаточно близко, побегут что бы ударить)
    • Дальники оббегают препятствия, если не могут выстрелить.
    • Есть встроенный инвентарь для лута после убийства.
    • Зона спауна
    • Список классов
    • Шанс спауна
    NPC
    • Городские NPC, патрулирующие свою зону спауна
    • Уникальные NPC
    • Базовый контроллер расписания для уникальных НПЦ
    • Реакция на урон (убегают или используют имеющееся оружие)
    • Встроенный инвентарь для лута после убийства.
    • Объектная диалоговая система
      • Дерево диалогов
      • Каждый ответ - объект
      • Для каждого ответа можно докинуть любую логику или условие доступности.
      • Интерфейс диалога
      • Несколько готовых классов ответа (запускает торговлю, забирает ресурсы, если есть, выходит из диалога)
    Строительство
    • Класс конструкций, которые поддерживают размещение
    • Использование предметов-ресурсов из инвентаря при размещении.
    • Снаппинг на некоторых типах конструкций (н.п. Стены, фундамент, окна)
    • Менюшка с конструкциями
    • Подсвечивание конструкций, на которые хватает ресурсов
    Дополнительно
    • Небольшая карта с городом, лесом, водоемами (можно плавать).
    • Система смены дня/ночи
    • Автомобили
      • Вид от первого или третьего. Общее с персом
      • Включение/выключение фар.
      • Встроенный компонент инвентаря (нужно взаимодействовать у багажника)
    • Кое как работающие лестницы вертикального типа.
    • Главное меню
    • Меню паузы
    • Меню с настройками графики

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

    Содержание по частям

    1. Начинаем и планируем проект. Создаем управление и поведение персонажа.
    2. Начинаем делать систему инвентаря.
    3. Продолжаем делать базу системы инвентаря.
    4. Готовим базу для экипировки и вооружения.
    5. Работа над оружием и использовании патронов.
    6. Делаем автострельбу и прицеливание.
    7. Создаем базовую систему крафта.
    8. Бег, переработка предметов и их износ.
    9. Реализовываем перезарядку для оружия.
    10. Делаем оружие ближнего боя.
    11. Доделываем ближний бой и делаем лестницу по которой можно взбираться.
    12. Делаем интерактивные предметы: Дерево, камень, кусты.
    13. Делаем HUD и начинаем делать интерфейс для инвентаря.
    14. Продолжаем работать над интерфейсом инвентаря. Делаем генерацию ячеек с предметами.
    15. Продолжаем делать генерацию ячеек и поиск места для предмета. Добавляем страницы инвентаря.
    16. Делаем небольшое взаимодействие с предметами в инвентаре и окно подробной информации.
    17. Сделали Drag&Drop перетаскивание предметов по инвентарю и в другой инвентарь.
    18. В этой части речь идет о визуализации крафта.
    19. Создаем окно с выбором количества предметов из стака для переброса в другой инвентарь.
    20. Делаем поддержку разных рецептов крафта, а так же фиксим разные баги у инвентаря.
    21. Создаем систему смены дня и ночи, а так же делаем новую сцену для нашего проекта.
    22. Начинаем создавать AI для агрессивных ботов.
    23. Делаем атаку мобов, а так же реакцию на атаку. Плюс реализуем сбор лута с мертвых мобов.
    24. Делаем зону спауна для нпц. Так же добавляем генерацию случайных предметов в инвентаре.
    25. Обновляемся до 4.13, а так же делаем дальних агрессивных нпц.
    26. Добавляем разные элементы на HUD. Добавляем ручную перезарядку оружия.
    27. Доделываем поддержку скелетной одежды и шапок. Добавляем анимацию для оружия от первого лица.
    28. Делаем интерфейс для работы с нашей системой экипировки.
    29. Начинаем делать торговую систему и компонент менеджмента денег.
    30. Продолжаем делать торговлю, создавая и настраивая компонент торговли.
    31. Делаем отмену торговли, а так же настраиваем анимацию перезарядки.
    32. Создаем транспорт со своим инвентарем, фарами и переключением вида. Создаем фонарик.
    33. Создаем строительство (а точнее систему размещения объектов перед собой).
    34. Делаем интерфейс для строительства, делаем привязку для стен.
    35. Создаем ещё несколько видов конструкций: Палатка, кровать, стул, стол, лампа, дверь. сундук, костер.
    36. Добавляем крышу, окна. Доделываем выравнивание относительно других конструкций.
    37. Делаем небольшое поселение, а так же населяем его NPC, которые так же создаем в этом уроке.
    38. Начинаем делать систему диалогов для наших жителей.
    39. Настраиваем туман и постобработку. Импортируем модель зомби и настраиваем ему анимации.
    40. Доделываем систему диалогов.
    41. Делаем взаимодействие с предметами от третьего лица, а так же модификаторы для брони.
    42. Создаем главное меню, меню паузы и настройки графики. А так же собираем первую сборку игры.
    43. Реализуем расписание для уникальных жителей.А так же что бы городские NPC убегали от атаки.
    44. Добавляем контекстное меню в инвентарь, а так же фиксим некоторые баги нашего инвентаря.
    45. Добавляем отдачу, разброс, анимацию выстрела и возможность ударить для огнестрельного оружия.
    46. Доделаем агрессивных и городских NPC, фиксим разные баги, связанные с ними.
    47. Настраиваем анимации для главного персонажа. Добавляем различную одежду.
    48. Исправляем различные ошибки в нашей игре.
    49. Исправляем различные ошибки крафта, NPC и экипировки в нашей игре.
    50. Немного дорабатываем карту и собираем последний билд.