Привет всем спонсорам!
Это традиционный (но в этот раз немного запоздалый) пост про итоги работы, в котором я расскажу, что интересного случилось с проектом за прошедший май.
Свежие мысли
Не все идеи приходят во время сфокусированного процесса мышления. Важно иногда делать перерывы и перезагружать своё сознание. Я ни раз замечал, что много полезных мыслей у меня появлялось именно во время отдыха или после него.
На майских праздниках я решил отдохнуть. Результатом выходных стали эти идеи:
1) Мне не нравится название проекта "Grim Wild". Во-первых, потому что "мрачная дикость" - это бессвязный набор слов, который никак с мультяшной игрой не синхронизируется. И уж тем более не поможет мне завлечь в игру больше игроков.
Во-вторых, потому что это словосочетание вообще означает "мрачный дикий", и тут даже нет существительного (смотря как интерпретировать).
Название Grim Wild в 2024 году перестало устраивать меня так же, как в прошлом "Grim World".
В общем, я пока думаю над вариантами. Мне необходимо оставить "Grim" и "Wild" для того, чтобы старая известность проекта не потерялась, но при этом убралась ошибка, а ещё схожесть с названием игры "Grim Dawn", с которой поисковики меня постоянно путают.
Самый простой вариант: добавить третье слово. Получится что-то вроде Grim Wild Planet или Grim Wild World (эпичный камбек слова "World").
Название стало бы уникальнее (сложнее спутать), старая аббревиатура была бы сохранена, а логическая ошибка исчезла бы с концами. В данном случае слова Grim и Wild становятся кумулятивными прилагательными, и запятая между ними не нужна.
2) Я придумал новое строение клеточной системы, которая заменяет собой старую "клетку уровня и клетку планеты". Понадобилась она мне для поддержки открытого мира и GPU симуляций (тепло, жидкости, воздух...).
Раньше моё сознание замыкалось на двух вариантах: клетка = контейнер с данными или клетка = игровой объект. Свежесть новой идеи состоит в том, что клеток не будет совсем. Весь их функционал берёт на себя чанк, где половина нужной нам информации хранится в обычных массивах (например, Id поверхностей), а всё остальное - в буферах GPU симуляций (тепло, жидкости, воздух, радиация...), которые становятся доступны для чтения на CPU.
С новой клеточной системы начнётся разработка версии 0.4. Да, наконец-то 0.3 уходит в историю! Но не прямо сейчас, а чуть позже (надеюсь, в июне). Всё-таки, кое-какие старые дела у меня ещё остались.
3) Контент для Бусти и Ютуба. Я написал черновик сценария "Как писать код и не сходить с ума", в котором рассказываю, как в одиночку уже четвёртый год занимаюсь растущей кодовой базой проекта и каким-то образом не теряюсь в механиках, планах и идеях. Правда, формат контента я пока не определил. Может, это будет пост, а может - видео. Но для ролика на Ютубе ещё далеко - для начала надо наработать репутацию.
Более краткосрочные планы у меня на контент для Бусти:
• "Почему Grim Wild бесплатный": объясняю, почему мне это выгодно даже с учётом серьёзности проекта.
• "Проблемы Grim Wild": технические и идейные сложности, которые мне предстоит решить. Я считаю, что спонсоры должны знать всю информацию о разработке, а не только её положительные стороны.
[Grim Wild]
Новая отрисовка (продолжение)
Система статических спрайтов была успешно доделана!
Правда, новые спрайты - это всего лишь часть новой системы отрисовки. Отложенное обновление трансформации и композитные текстуры будут сделаны позже, когда некоторые другие аспекты проекта будут проработаны детальнее.
Подробнее про работу в мае:
• Сделана механика пула спрайтов (Sprite Component Pool).
Когда по какой-то причине спрайт на сцене нам больше не нужен (например, если игрок ушёл из чанка, или объект был уничтожен), мы его не удаляем, а сохраняем для повторного использования. Это очень полезно в открытом мире, где игрок может перемещаться по бесчисленному количеству чанков. Ведь ресурсы для отрисовки их содержимого нам создавать с нуля не нужно! Они просто "отстыковываются" от старого владельца и переходят к новым.
(минутка технических подробностей)
В GW реализация пула усложнялась принципом работы статических спрайтов. Команды для отрисовки здесь кэшируются, а Draw Calls агрессивно объединяются (Draw Commands Caching + Draw Call Merging). Это всё говорит о том, что менять CPU параметры спрайта на сцене после создания уже нельзя. У него должен оставаться старый шейдер со старыми параметрами. То есть со старым текстурным атласом. Единственное, что менять можно - это параметры в видеопамяти (VRAM): оттенок материала (древесина, золото...) и UV слота в текстурном атласе.
Получается, что компоненты (Sprite Components) могут быть повторно использованы только для спрайтов из того же текстурного атласа. В будущем я реализую механику автоматического определения размера пула спрайтов, чтобы там хранилось оптимальное количество "запасных" компонентов: и не слишком мало (тогда приходилось бы создавать всё новые и новые ресурсы), и не слишком много (тогда запасные компоненты лежали бы в пуле слишком долго и напрасно занимали ОЗУ).
Также у меня на будущее заготовлена автоматическая очистка старых и неиспользуемых компонентов в запасе.
• Runtime текстурный атлас: добавление региона изначальной текстуры.
На runtime текстурный атлас теперь можно добавлять не всю изначальную текстуру, а только её определённый участок (регион). Под изначальной текстурой подразумевается файл, который я или мододелы загружаем в проект.
Использоваться это будет для направленных спрайтов, изначальная текстура которых имеет три направления (верх, низ, сторона).
Ровно такая же логика будет нужна и для того, чтобы определённые спрайты из runtime текстурного атласа можно было расположить на какой-то другой текстуре. Например, иконки на UI для каждого колониста игрока - это текстуры, строящиеся из спрайтов текстурного атласа, которые расположены на разных его участках.
• Спрайты, не использующие runtime текстурный атлас.
Не все спрайты должны добавляться в RTA (Runtime Texture Atlas).
1) Если спрайт слишком большой (например, 1024x1024 пикселей), он собой займёт сразу 25% всего атласа. Проще отрисовывать его отдельным Draw Call'ом.
2) Если спрайт слишком редкий (например, игрок увидит его всего 1 раз за всю игру), то в RTA он будет напрасно занимать место и не использоваться совсем.
3) И, наконец, есть ещё блоки. В игре у них 46 визуальных вариаций: Они импортируются в проект в виде атласа и при динамической загрузке ассета подгружаются все сразу. Нет смысла перемещать 46 спрайтов из родного атласа в другой; проще создать один лишний Draw Call.
Называются такие спрайты "Non-CRT" (Non Canvas Render Target). Они поддерживают все фишки статических спрайтов, просто используют свою собственную текстуру.
• Sprite Data: новые типы.
SpriteData - это ассет, который заменяет Paper Sprite. Он состоит из ObjectSprite'ов. Вот наглядная схема:
Ассет "каски" содержит три внутри спрайта для каждого направления.
Раньше SpriteData разделялась на Regular ("обычную", 1 направление) и Directed ("направленную", 3 направления).
В мае добавились типы "TileSet" ("набор блоков") и Custom ("кастомный").
TileSet содержит в себе любое количество ObjectSprite'ов (см. например, 46), где у каждого из них есть своё условие:
Например, у блока под индексом [25] условие такое: Соседи, которые должны быть заняты: С, СВ, В
Соседи, которые должны быть свободны: Ю, ЮЗ, З
А Custom тип нужен для всех остальных случаев, когда нам для одного спрайта нужно несколько визуальных вариаций. Например, все растения в игре имеют несколько стадий роста:
Ещё может добавиться "сгнившая" стадия. Ограничений в этом плане нет
• Удаление спрайтов из атласов.
Теперь спрайты в runtime текстурные атласы можно не только добавлять, но и удалять.
В будущем я сделаю механизм автоматического удаления всех ненужных спрайтов (например, которые не использовались игрой на протяжении 15 реальных минут). Это позволит использовать старые слоты повторно и держать полезную нагрузку атласа на высоком уровне.
На такой шаг мне пришлось пойти из-за отказа от runtime текстурной компрессии, которая значительно бы снизила размер атласов в ОЗУ и видеопамяти. Она оказалась слишком проблемной, и проще было отказаться от неё сразу, чтобы не тратить время впустую.
Вместо оптимизации системы отрисовки с помощью компрессии у меня будет оптимизация с помощью поддержания атласов в свежем состоянии, где все спрайты нам точно полезны.
• Незначительные изменения:
• Вся система статических спрайтов теперь доступна для отладки в консоли разработчика. Это будет полезно для закрытого тестирования.
• Рисование на RTA теперь происходит не сразу при добавлении спрайта, а в конце текущего кадра для всех элементов сразу. Это позволит уменьшить нагрузку во время загрузки игры, когда на сцену добавляется очень много спрайтов одновременно.
• Появилась возможность размещать на текстурном атласе файлы с диска. Именно так будут работать моды.
• Исходная текстура спрайта после добавления в текстурный атлас теперь выгружается из памяти, потому что нам она больше не нужна.
• SpriteData теперь можно редактировать в C++/Lua. Это значит, что моды смогут добавлять свои спрайты, а также менять существующие в базовой игре данные (текстуру, сокеты).
• Редактор спрайтов, созданный мной для себя самого, продолжает улучшаться. Теперь там есть просмотр точки опоры (pivot point), коллизии и полезного пространства в текстурном атласе. Появилась поддержка просмотра Non-CRT спрайтов.
Поклеточные симуляции (тесты)
В седьмой серии видео я расскажу про поклеточные GPU симуляции, с помощью которых в игре будут работать жидкости, кислород, тепло и радиация.
На фон во время разговора на эту тему мне нужна демонстрация работы симуляций. А для этого мне нужны сами симуляции в игре (хоть в каком-то виде). И именно этим я и начал заниматься в мае.
Пока что у меня нет для вас интересных картинок. Я проверял свои догадки и решал создаваемые во время их реализации проблемы.
Главные вопросы по состоянию на июнь - это взаимодействия симуляций между собой (например, лава - это жидкость, которая также выделяет тепло) и обработка клеток в открытом мире + взаимодействие значений между чанками (прогруженными и непрогруженными).
Игровое время и важность объектов (в процессе)
Во второй серии видео я рассказывал про интересную систему течения внутриигрового времени: у "неважных" для игрового процесса объектов логика выполняется реже, чем у "важных".
Например, у (важного) колониста игрока раз в секунду отнимается 1 единица сытости.
А у (неважной) дикой курицы, которая находится где-то далеко на границе чанка, раз в три секунды отнимается 3 единицы сытости.
Курица имеет меньшую нагрузку на компьютер игрока, но имеет более высокую погрешность в логике. Но для нас это должно быть неважно.
Но что такое "важные" объекты? Откуда эта "важность" берётся и как меняется?
В мае у объектов появился набор пометок (флагов) под названием Gameplay Relevance. С его помощью мы определяем и то, как часто объект обновляется, и нужно ли его сохранять на диск. А может, при выгрузке чанка он тут же удалится из-за своей бесполезности.
Пример: Если объект принадлежит фракции игрока, его релевантность всегда высокая. Это значит, что тики у него сжиматься не будут + он сохранится на диск + чанки, где есть постройки игрока, всегда будут прогружены.
По поводу игрового времени: сейчас, когда нужды у проекта изменились, и здесь, например, появились GPU симуляции, делать ускорение времени с помощью сжатия тиков до каких-то аномальных значений нельзя.
Придётся использовать классическое увеличение TPS (Ticks per Second). А это значит, что на скорости x10, вопреки сценарию второй серии, тормозить всё-таки будет. Но нам ведь и не нужна скорость x10!
[Публичная деятельность]
Сценарий новой, седьмой серии продолжает дополняться, но есть одна загвоздка.
Я уделяю там очень много времени новым идеям и планам. То есть тому, чего в игре пока нет. То есть тому, для чего мне придётся делать футажи почти с нуля (например, GPU симуляции).
Конечно, я могу нарисовать очередную порцию схем со стрелочками. Но не очень хочу продолжать "скрывать" реальный проект от зрителей. Мне (и, надеюсь, зрителям) хочется видеть в ролике сам Grim Wild!
В общем, с седьмой серией всё сложно. В июне я начну активно ей заниматься, но доделаю ли все запланированные дела - пока не до конца понятно. Это и есть основные планы на июнь.
Спасибо за внимание!