Messages in this channel will be automatically deleted after 1 month
Messages in this channel will no longer be automatically deleted
Media is too big
VIEW IN TELEGRAM
Ну вот, пришло время написать первый пост по игре, над которой я работаю уже достаточно много времени.
Что за игра, в каком жанре, чем отличается и многие другие моменты будут описаны чуточку позже. А пока, делюсь результатами по первой фиче, которую вообще можно показать (а не только рассказать про код, технологии и фреймворки😄 ).
Я наконец-то реализовала возможность изменять ландшафт, что позволяет, например, вырыть пещерку (ура!💃 )
Что за игра, в каком жанре, чем отличается и многие другие моменты будут описаны чуточку позже. А пока, делюсь результатами по первой фиче, которую вообще можно показать (а не только рассказать про код, технологии и фреймворки
Я наконец-то реализовала возможность изменять ландшафт, что позволяет, например, вырыть пещерку (ура!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20
Channel name was changed to «Infinity World (Дневники разработчицы)»
Комментарии открыла, должно работать, но к старым постам это не относится :( Но можете и под этим оставить 💃
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰3🆒2👍1
Также присоединяйтесь к чату этой группы https://t.me/+P2tyt0x2ccI4M2Zi (в шапке канала ссылка на чат также есть). Там можно в том числе и мне задавать вопросы 🥔
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
Infinity World (dev) Chat
You’ve been invited to join this group on Telegram.
🥰5
Меня в комментариях спрашивали, на чем базируется копание ландшафта, поэтому я решила немного рассказать о своем фреймворке прежде, чем начну вести сами дневники разработки по текущим задачам.
Я не использую уже готовые решения по той причине, что они или медленные или совсем не гибкие, а для реализации моих идей нужно и то и то) Я также не использую стандартный ландшафт от Unity, так как это совсем не про бесконечную бесшовную генерацию. По этой причине я решила написать свое решение.
С самого начала я определилась с некоторыми технологиями, которые буду использовать - Jobs + Burst. Эта связка дает слишком много, чтобы не быть использованной. Но, по ходу моих постов, вы скорее всего задатитесь вопрос: "А почему не GPGPU?". И ответ тут не так уж чтобы и простой. Одна из итераций у меня была на Compute Shaders, результаты по производительности впечатляющие, пока не начинаешь передавать данные (сгенерированные меши) с GPU на CPU. А это необходимо хотя бы в рамках построения физических коллайдеров. Также, вычислительные шейдеры - это не про гибкость, хотя часть моментов, например граф генерации шума, можно решить через кодогенерацию. Но я же вроде бы игру делаю, а не инструмент под Unity?👏
Другая часть технического стэка была выбрана по ходу исследований и множества итераций. Если Jobs + Burst я использую для генерации, то что для представления?
С самого начала я думала использовать подход ECS, уж очень он гибкий по сравнению с классическим ООП. Но какой фреймворк взять? Вначале я взяла Leo ECS Lite (не реклама), с которым я раннее работала и который мне очень понравился своей простотой. Но потом, когда я изучала BRG и интегрировала его к себе в проект, мне подсказали, что UECS из пакета DOTS, вполне себе уже используемый (все мы знаем про UECS, да? 🤪 ). И я, соблазнившись избавлением от GameObject, получением BRG из коробки для всего, что я захочу отрисовать, перешла на него. Хотя тот же BRG все равно использую в задачах, где даже entity можно не создавать.
Еще работая "на дядю" я мечтала, что не буду использовать uGUI (не буду рассказывать почему, подозреваю, что вы и так знаете), а возьму что-нибудь WPF-like. Поэтому в своей игре я сразу сделала ставку на NoesisGUI - WPF-like фреймворк с MVVM из коробки. Сейчас конечно уже появился UIToolkit, и даже с нормальными биндингами (те, которые runtime), но хотелось более мощное решение. Кстати, Baldur's Gate 3 тоже использует NoesisGUI☺️ .
Что касается сетевой части (да-да, она уже в каком-то виде даже есть, и изменение ландшафта синхронизируется между сервером и клиентами), выбора у меня было немного, раз я на UECS - Netcode for Entities. Авторитарный сервер (вместо p2p) конечно усложняет жизнь, но примеров достаточно, а также есть доброжелательное комьюнити. О том, как я решила задачу синхронизации ландшафта (как генерации так и изменения) я опишу чуть позже🫥
Итого, мой основной технический стэк выглядит вот так:
- Unity
- DOTS (Jobs, Burst, UECS, BRG)
- Netcode for Entities
- NoesisGUI
Я не использую уже готовые решения по той причине, что они или медленные или совсем не гибкие, а для реализации моих идей нужно и то и то) Я также не использую стандартный ландшафт от Unity, так как это совсем не про бесконечную бесшовную генерацию. По этой причине я решила написать свое решение.
С самого начала я определилась с некоторыми технологиями, которые буду использовать - Jobs + Burst. Эта связка дает слишком много, чтобы не быть использованной. Но, по ходу моих постов, вы скорее всего задатитесь вопрос: "А почему не GPGPU?". И ответ тут не так уж чтобы и простой. Одна из итераций у меня была на Compute Shaders, результаты по производительности впечатляющие, пока не начинаешь передавать данные (сгенерированные меши) с GPU на CPU. А это необходимо хотя бы в рамках построения физических коллайдеров. Также, вычислительные шейдеры - это не про гибкость, хотя часть моментов, например граф генерации шума, можно решить через кодогенерацию. Но я же вроде бы игру делаю, а не инструмент под Unity?
Другая часть технического стэка была выбрана по ходу исследований и множества итераций. Если Jobs + Burst я использую для генерации, то что для представления?
С самого начала я думала использовать подход ECS, уж очень он гибкий по сравнению с классическим ООП. Но какой фреймворк взять? Вначале я взяла Leo ECS Lite (
Еще работая "на дядю" я мечтала, что не буду использовать uGUI (не буду рассказывать почему, подозреваю, что вы и так знаете), а возьму что-нибудь WPF-like. Поэтому в своей игре я сразу сделала ставку на NoesisGUI - WPF-like фреймворк с MVVM из коробки. Сейчас конечно уже появился UIToolkit, и даже с нормальными биндингами (те, которые runtime), но хотелось более мощное решение. Кстати, Baldur's Gate 3 тоже использует NoesisGUI
Что касается сетевой части (да-да, она уже в каком-то виде даже есть, и изменение ландшафта синхронизируется между сервером и клиентами), выбора у меня было немного, раз я на UECS - Netcode for Entities. Авторитарный сервер (вместо p2p) конечно усложняет жизнь, но примеров достаточно, а также есть доброжелательное комьюнити. О том, как я решила задачу синхронизации ландшафта (как генерации так и изменения) я опишу чуть позже
Итого, мой основной технический стэк выглядит вот так:
- Unity
- DOTS (Jobs, Burst, UECS, BRG)
- Netcode for Entities
- NoesisGUI
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20❤11👍6👎1
Меня еще спросили, можно ли насквозь "прокопать" ландшафт. И мой ответ - да! Немного видео по фиче изменения ландшафта. И можно не только "копать", но и "возводить" 💃
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍6❤2👎1
Генерация. Воксели
"Весь мир должен генерироваться" - моя первая мысль, когда я только задумывалась об игре)
И прежде чем генерировать всякие красивости и бегающих за игроком лисичек, надо было сгенерировать ландшафт. Самое первое решение, которое у меня получилось, было очень и очень простым: генерируем простенький шум (Perlin например), где значение шума - оффсет для вершин. Дальше двигаем вершины, например в Compute Shaders, и получаем ландшафт. Такой метод используется в Valheim. Выглядит хорошо, если увеличить плотность сетки мешей, работает очень быстро, легко распараллелить. Но есть и один очень большой минус - ландшафт не может иметь сдвиги по горизонтали, а значит никаких пещер, нависающих скал и прочих деталей, которых мне так хотелось.
Поняв, что решение в лоб мне не подходит, я начала искать другие методы генерации. И вскоре пришла к идее вокселей. Самые популярные примеры воксельных миров - Minecraft и No Man's Sky (а сейчас еще и Enshrouded).
Что такое воксель? Его можно описать как куб пространства с каким-либо значением. Прямой сосед вокселю - пиксель, который живет в 2D мире, тогда как воксель - в 3D мире. В моей задаче каждый воксель хранит значение с плавающей запятой со знаком, то есть обычный float. Это значение означает дистанцию до поверхности, где отрицательное значение - мы под поверхностью, а положительное - над ней. Значение 0 же является самой поверхностью. Такое поле дистанций имеет свое название - Signed Distance Field (SDF). Хотя во многих источниках это значение называется плотностью (density), но мне лично помогло осознать алгоритм именно через дистанцию.
Также воксель еще хранит значение градиента SDF. Что такое градиент? Это вектор изменения значений (дистанций) в каждом вокселе. Чтобы его вычислить нам необходимо знать соседние значения SDF (это уже затык для параллелизации в будущем). Но в общем случае вычисление выглядит вот так:
На основе градиента вычисляются как позиции вершин, так и их нормали, но об этом расскажу в следующих постах. Также и про генерацию шума расскажу чуть позже)
"Весь мир должен генерироваться" - моя первая мысль, когда я только задумывалась об игре)
И прежде чем генерировать всякие красивости и бегающих за игроком лисичек, надо было сгенерировать ландшафт. Самое первое решение, которое у меня получилось, было очень и очень простым: генерируем простенький шум (Perlin например), где значение шума - оффсет для вершин. Дальше двигаем вершины, например в Compute Shaders, и получаем ландшафт. Такой метод используется в Valheim. Выглядит хорошо, если увеличить плотность сетки мешей, работает очень быстро, легко распараллелить. Но есть и один очень большой минус - ландшафт не может иметь сдвиги по горизонтали, а значит никаких пещер, нависающих скал и прочих деталей, которых мне так хотелось.
Поняв, что решение в лоб мне не подходит, я начала искать другие методы генерации. И вскоре пришла к идее вокселей. Самые популярные примеры воксельных миров - Minecraft и No Man's Sky (а сейчас еще и Enshrouded).
Что такое воксель? Его можно описать как куб пространства с каким-либо значением. Прямой сосед вокселю - пиксель, который живет в 2D мире, тогда как воксель - в 3D мире. В моей задаче каждый воксель хранит значение с плавающей запятой со знаком, то есть обычный float. Это значение означает дистанцию до поверхности, где отрицательное значение - мы под поверхностью, а положительное - над ней. Значение 0 же является самой поверхностью. Такое поле дистанций имеет свое название - Signed Distance Field (SDF). Хотя во многих источниках это значение называется плотностью (density), но мне лично помогло осознать алгоритм именно через дистанцию.
Также воксель еще хранит значение градиента SDF. Что такое градиент? Это вектор изменения значений (дистанций) в каждом вокселе. Чтобы его вычислить нам необходимо знать соседние значения SDF (это уже затык для параллелизации в будущем). Но в общем случае вычисление выглядит вот так:
public float3 ComputeGradient(float x, float y, float z, int seed)
{
var x1 = ComputeDensity(x + 1, y, z, seed);
var x2 = ComputeDensity(x - 1, y, z, seed);
var y1 = ComputeDensity(x, y + 1, z, seed);
var y2 = ComputeDensity(x, y - 1, z, seed);
var z1 = ComputeDensity(x, y, z + 1, seed);
var z2 = ComputeDensity(x, y, z - 1, seed);
return math.normalize(new float3(x1 - x2, y1 - y2, z1 - z2));
}
На основе градиента вычисляются как позиции вершин, так и их нормали, но об этом расскажу в следующих постах. Также и про генерацию шума расскажу чуть позже)
🔥12🤝4👍2👎1