Дневник разработки #8: свои эффекты, от плоских картинок до живого дыма
В этой части я рассказываю про эффекты: взрывы, дым, огонь, вспышки выстрелов, пыль и искры. Я заменил их в игре целиком, и по дороге мне пришлось сменить подход три раза. Сразу оговорюсь: все замеры сделаны на одной машине, в тестовой сборке и в одной сцене боя, живых игроков с этими эффектами я ещё не пробовал, и в конце есть список того, что не доделано.
С чего я начинал
Прежние эффекты игры собраны из процедурных текстур: шум и мягкие круги. Они выглядят как шарики, и взрыв у меня был тёмным мягким пятном без формы. Мне нужно было что-то ближе к тому, что делают в Niagara или Houdini, поэтому я решил не подбирать готовые наборы, а сначала проверить, насколько далеко можно уйти от этого начала.

На скриншоте четыре этапа через секунду после взрыва. Слева сверху прежний эффект, справа сверху флипбук, слева снизу объёмный дым, справа снизу живая симуляция. Камера и время на кадрах не совпадают полностью: последний кадр снят через 1,2 секунды и ниже, чтобы была видна высота столба.
Флипбуки
Первым шагом стали флипбуки: готовая бесплатная симуляция взрыва запекается в атлас из кадров, и эти кадры проигрываются на плоских квадратах. Результат был намного лучше прежнего. Камера в игре смотрит сверху под углом от 40 до 68 градусов и вращается, поэтому у квадрата видно край, а силуэт одинаков со всех сторон.

На скриншоте дым на этом этапе: форма плоская, а край зернистый, как будто его вырезали по маске. Это и есть то, что мне не понравилось.
Объёмный дым
Я решил отказаться от системы частиц Unity, потому что в ней нельзя контролировать всё, что нужно, и сделать свою. Первый шаг был таким: готовая симуляция дыма хранится не как кадры, а как трёхмерная текстура, и дым рисуется лучами, которые проходят сквозь неё. Тогда дым получил объём: его можно обойти камерой и видеть с любой стороны. Но у этого этапа тоже нашлись жалобы: эффекты объёмные по факту, но визуально плоские, глубины не хватает.
Своя симуляция дыма и огня
Дальше я сделал решатель, который считает дым и огонь на видеокарте: сетка до 256 ячеек по длинной стороне, скорость и плотность в каждой ячейке, как в Houdini Pyro. Для игры результат можно запекать в объём, это дёшево, а крупные эффекты можно играть живьём. Свой решатель удобнее готовой симуляции тем, что вариантов можно получить сколько угодно, а не один.

На скриншоте один и тот же столб дыма до и после правок качества рендера объёма. Справа дым темнее внутри, на нём видны складки, а на земле лежит тень.

На ролике три взрыва подряд в живой симуляции.
Движок частиц и редактор
Одной симуляции для игры мало, нужны ещё вспышки, искры, трассеры, обломки, декали и свет. Поэтому я сделал универсальный движок эффектов, а не отдельные эффекты. Частицы считаются на видеокарте, в одном пуле их до 130 тысяч. Эффект состоит из эмиттеров, а каждый эмиттер из стека модулей, как в Niagara: рождение, изменение по жизни, силы, столкновения, отрисовка. Рисовать можно спрайтами и лентами, мешами, объёмами, декалями и светом, к ним добавляются тряска камеры и звук.

На скриншоте окно редактора эффектов. Слева библиотека эффектов по папкам, в центре просмотр взрыва с таймлайном, справа стек модулей выбранного эмиттера, а над просмотром строка с замером времени видеокарты по проходам. При замере 50 тысяч добавляющихся частиц в одном облаке стоят около 0,09 миллисекунды видеокарты.
Эффекты в игре
Новый движок подключился к игре. Набор состоит из 74 эффектов: взрывы разных размеров, попадания по классам брони, вспышки выстрелов по калибрам, гибель юнитов и зданий, и т.д. Старая система осталась запасной: в настройках графики есть выключатель «Новые эффекты». Погода теперь влияет на эффекты: ветер сносит частицы и дым, а дождь гасит огонь и пыль.

На скриншоте бой в игре: трассеры, вспышки выстрелов, огонь и дым на горящей технике. Карта на этом кадре тёмная из-за ошибки в настройке солнца, которую я ещё не исправил, к эффектам она не относится.
Когда я посмотрел эффекты в игре, мне сразу не понравились их размеры: попадания и взрывы были слишком длинными и большими. Поэтому я ввёл нормы. Попадание не больше юнита и не дольше 0,8 секунды, взрыв снаряда или техники около 2,5 секунды и 6 единиц в размере и т.д. Все эффекты подгоняются к этим нормам при сборке, и есть тест, который проверяет, что ни один из них не выходит за границы.

На ролике в замедлении дым от разрушенного здания.
Сколько это стоит
Я замерил цену эффектов в бою: две армии у центра карты, около 110 юнитов и два здания, разрешение 1920 на 1080, тестовая сборка, видеокарта RTX 4070 Laptop. В игре есть четыре уровня качества эффектов, от Низкого до Ультра: чем выше уровень, тем больше частиц и источников света, а на Ультра дым считается живой симуляцией.

На графике добавка к времени кадра на видеокарте. Старые эффекты стоили 0,6 миллисекунды, новые на Высоком от 3,2 до 3,4, и это укладывается в бюджет 3-4 миллисекунды, который я себе поставил (голубая полоса). Весь кадр вырос с 9,5 миллисекунды без эффектов до 14,2-14,5 на Высоком, потому что часть цены приходится не на видеокарту.
Что не доделано
Туман войны пока не доходит до шейдеров частиц: эффекты гасятся по тому, исследована ли клетка, а туман рисуется поверх. При огнях эффектов в тестовой сборке остаётся мусор в памяти около 3 килобайт на кадр, и его надо разобрать профайлером. У флипбуков пока нет освещения с шести сторон и т.д. Старые эффекты я не удаляю: они остаются запасным путём, пока новые не пройдут плейтесты.
Что дальше
Дальше я хочу проверить эффекты на картах с разными сезонами и погодой, потом провести плейтест и только после этого убирать старую систему. Отдельной задачей остаётся туман войны для частиц.
