Infinity World (Дневники разработчицы)
439 subscribers
52 photos
24 videos
37 links
Канал-дневник разработчицы на Unity, рассказываю о всяком интересном и не очень, что встречается на пути разработки.

Тех стэк:
- Unity
- DOTS
Download Telegram
StructLayout.Pack и Burst

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

Для того, чтобы управлять тем, как члены структуры расположены в памяти, мы можем обратиться к атрибуту StructLayout, который имеет несколько параметров.

Note: атрибут StructLayout может применяться также и к классам!

1️⃣ Первый параметр - LayoutKind - тип макета, который бывает:
1. Sequential: все поля располагаются в памяти последовательно в порядке объявления.
2. Explicit: поля располагаются в памяти по заданным смещениям. Эти смещения указываются через атрибут FieldOffset.
3. Auto: автоматическое расположение полей в зависимости от компилятора. Совсем не обязательно, что поля будут располагаться в порядке объявления, так что с этим поосторожнее.

Note: по умолчанию всегда стоит Sequential, то есть получаем поведение из пункта 1.

2️⃣ Второй параметр, который тоже частенько используется - Size. Он отвечает за абсолютный размер структуры. Используется, когда мы хотим выделять конкретное количество байт на структуру. Причем, мы можем выделить больше, чем поля в сумме занимают на самом деле. Таким образом можно, например, выделить кусочек памяти на header структуры и там хранить какую-то информацию.

Note: размер структуры без каких-либо полей равен одному байту. Так что не обязательно указывать Size = 1 у "пустой" структуры.

3️⃣ Третий параметр - CharSet - задает кодировку для строк. Но в рамках Burst это мало интересует. Но может понадобиться, если работа ведется с неуправляемыми библиотеками.

4️⃣ И четвертый параметр - Pack - задает выравнивание полей. Тоже может использоваться частенько, но надо быть очень осторожным с ним. Полезен, если мы хотим, чтобы структура не занимала лишнее место в памяти, если используем поля с разным размером.

Давайте придумаем пример:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ExampleStruct
{
public byte ByteValue;
public int IntValue;
public short ShortValue;
}


Какой размер у такой структуры? Ответ - 7 байт. Почему? Потому что мы указали выравнивание 1 байт, тогда: поле ByteValue занимает 1 байт, поле IntValue занимает 4 байта и поле ShortValue - 2 байта. Если указать Pack = 4, то размер структуры будет уже 12 байт, по 4 байта на каждое поле.

Вроде бы все логично, но не для Burst: до версии 1.8.16 включительно было замечено такое поведение, что Burst пытается вставить свое выравнивание. Возможно это связано с векторизацией 🤷, но это приводит к тому, что в коде без Burst, структура занимает N памяти, например, те же 7 байт, а в коде с Burst, это структура будет занимать уже 16 байт.

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

Как с этим справляться? Я пока не придумала лучше того, чтобы совсем не использовать Pack. Но иногда так хочется, хочется сэкономить пару байт (да-да, я часто использую поля с размером 1 байт). А потом вспоминаю, как я искала неделю причину краша. 🤦

Когда-то Burst поддерживал только частично параметр Pack, сейчас в документации написано, что полностью поддерживает. Но все равно будьте осторожны!

P.S.: возможно кто-то сталкивался с подобным, поделитесь в комментариях!

#programming
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍7🔥4🥰1
This media is not supported in your browser
VIEW IN TELEGRAM
Редакторы тоже важны

Возвращала инстансинг объектов, и столкнулась с тем, что совсем не помню, что и как указывать в LOD. Я просто не могла настроить свои же лоды! 😔

Причина в том, что там надо указывать процентное отношение объекта к размеру камеры, а не какие-то понятные единицы. Это отношение еще надо посчитать, ох, лучше я редактор напишу ☺️

Взяла за основу редактор от UnityEngine.LODGroup - он понятен и привычен. Переписала его под свои нужды: в моей реализации LOD многое упрощено, да и работаю я напрямую с Mesh и Material, так как моя реализация под BRG.

Что ж, часа 4, и вот, PropertyDrawer, который почти повторяет функционал LODGroup. Рисуется в MonoBehaviour, ScriptableObject, везде, где указано сериализованное поле моего типа. Удобненько. 🥔

#programming
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1410👍2
Возвращение заблудших фич

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

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

По результатам оптимизации я писала пост вот туть.

Просто пост радости, теперь можно продолжить работать над ГД, добавлять новые возможности и идти к новым горизонтам, даже если из этого проекта ничего не получится.

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
27
Когда ты инди-разработчица, то приходится делать абсолютно все: продумывать геймдизайн, разрабатывать геймплейные фичи, инструменты, оптимизировать свой же код и графику, рисовать текстуры и моделировать объекты. Направлений просто куча! 😧

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

Последнюю неделю я изучала Adobe Substance 3D Designer: очень мощный инструмент для создания разнообразных текстур. Правда оказался достаточно сложным для меня: после тысячи часов за кодом снова вернуться к арту - задачка та еще)

Зато этот инструмент довольно близок ко мне по духу: шум, много шума, очень много шума и различные операции над ним. Тяп-ляп, и текстура готова 😄 Процесс почти такой же, что и у меня в генераторе мира)

#texturing
Please open Telegram to view this post
VIEW IN TELEGRAM
16🔥5😱2🥰1
Нас уже 300 человек! Удивительно Спасибо вам всем за поддержку! ❤️

Я немного отдыхала в последнее время и не работала над проектом, поэтому пока нового не покажу. Но, я скоро вернусь за работу и там будет очень много интересного по графике, по сетевой части, по геймплею и многому другому!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥287💋7🎉21
Написала статью по новому этапу разработки 👏 Будет серия постов и статей.

К сожалению, telegraph больше не поддерживается telegram, поэтому пришлось переехать на teletype 🧂 Надеюсь вам будет удобно читать! 🥰

Русская версия: вот тут.
English: here.

#game_design #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14💋52😍2
Entities (DOTS) и Wireframe режимы

Когда я только начала использовать DOTS и использовать BatchRendererGroup (BRG), то столкнулась с тем, что посмотреть сетку мешей в окне сцены невозможно. Переключалка в Scene View работает только для GameObject и MeshRenderer, а для сущностей, которых на сцене фактически то и нет, уже не работает. 😭

Учитывая, что вся геометрия у меня процедурно генерируется, посмотреть получившуюся сетку было жизненно необходимо. Я спасалась тем, что был отдельный debug MonoBehaviour, который умел генерировать отдельные чанки и запихивать их в MeshRenderer. Неудобно, скажите вы, и будете абсолютно правы. 😔

Что же делать? Использовать Rendering Debugger! Подробное описание можно найти вот тут. В Unity его можно найти в меню Window -> Analysis -> Rendering Debugger. Там на самом деле множество полезных инструментов для дебага графики, но что меня порадовало в свое время - есть wireframe режимы, которые работают и с сущностями!

Чтобы переключить wireframe режим, надо найти выпадающий список по пути Rendering -> Rendering Debug -> Additional Wireframe Modes в окошке Rendering Debugger. Вдруг кому-нибудь полезно будет ☺️

#dots
🔥194👀4💋2
Демо-сцена. Форма ландшафта.

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

Русская версия: вот тут.
English: here.

Приятного чтения! 🥰

#generation #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥104🥰2💋1
Custom properties в DOTS Instancing

Как и в GPU Instancing, в DOTS Instancing есть определенные правила работы с полями, которые должны быть per instance. 🧐

Если рассматривать как в DOTS Instancing устроено хранение данных для каждого инстанса, то стоит обратиться к Batch Renderer Group. А там, фактически, один буфер, где под каждое поле (будь то матрица или просто цвет) выделяется определенный кусок памяти. Дальше, с помощью оффсетов, которые можно вычислить, зная размер данных поля и количество интансов, можно получить доступ к конкретному значению конкретного поля для конкретного инстанса.

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

Определение поля:
#ifdef UNITY_DOTS_INSTANCING_ENABLED
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, _ChunkDebugColor)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
#else
int _ChunkDebugColor;
#endif


И получение значения:
float4 debug_color = (float4)0;
#ifdef UNITY_DOTS_INSTANCING_ENABLED
debug_color = UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, _ChunkDebugColor);
#else
debug_color = _ChunkDebugColor;
#endif


Но как же указать значение для инстансов? 🤔
Когда мы работаем с GPU Instancing, то необходимо передать буфер per property, который мы можем как-то заполнить на стороне CPU. В случае же с DOTS Instancing, мы должны работать с буфером BRG и заполнять его. Это немного сложновато, но у меня есть небольшая реализация, которая упрощает этот процесс.

Но также есть и другой способ, если используется пакет Entities. Там мы можем указывать значения через компоненты!
Для этого необходимо создать небольшой компонент и повесить его на сущность, все остальное за нас сделает Unity:

[Serializable]
[MaterialProperty("_ChunkDebugColor")]
public struct DebugChunkColorProperty : IComponentData
{
public float4 Value;

public static implicit operator DebugChunkColorProperty(float4 value)
{
return new DebugChunkColorProperty
{
Value = value
};
}
}


#dots
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥124👏3👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Что такое Biome?

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

Так как воксели генерируются у меня на стороне GPU (использую вычислительные шейдеры), то правила генерации ландшафта и выбор типов вокселей описываются на языке HLSL.

Фактически, это просто математическое уравнение. Довольно большое и сложное, но все же уравнение: на входе позиция в world space и зерно (seed) мира, а на выходе - дистанция для Signed Distance Field и вектор типов вокселей, которые могут быть в указанной точке пространства. Вот и все 👏

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🥰3😍21💋1
Демо-сцена. Базовые цвета ландшафта. Часть 1.

На этот раз затрагиваю тему материалов вокселей и базовых цветов ландшафта для демо сцены.

Это первая часть статьи, так как для продолжения необходимо вначале настроить освещение 👏

Русская версия: вот тут.
English: here.

Приятного чтения! 🥰

#generation #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
10💋4🔥1😢1
Вынужденный 🤭 отпуск закончился и я возвращаюсь потихоньку за работу! 🥔
Please open Telegram to view this post
VIEW IN TELEGRAM
18🔥12❤‍🔥4💋1
Начала работать над блокингом сцены: расставляю вначале крупные детали, потом перейду к средним, и в конце уже к мелким. 👏

Заодно дописываю генерацию, так как появляются разные небольшие моменты, о которых раньше и не предполагала) Например, для будущих камушков и скал на склонах надо учитывать нормаль, а не просто рандомно поворачивать 🤔

#generation #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
👍143🔥2💋2🆒2
Когда настраиваешь освещение/пост-процессинг/цвета, то очень быстро глаза "замыливаются" 🧂 Я с этим борюсь тем, что переключаюсь на другую задачу, и через некоторое время снова возвращаюсь к настройке.

Что получилось настроить на текущий момент внутренними средствами Unity по освещению и пост-процессингу можно увидеть на скриншотах 🙌

Где:
1️⃣ Совсем без освещения и пост-процессинга.
2️⃣ Промежуточный вариант освещения и пост-процессинга. Уже лучше, но цвета тусклые + оттенок слишком сильно уходит в зеленый.
3️⃣ Текущий вариант. Цвета стали сочнее, зеленый оттенок стал меньше.

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

#demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7🔥6👏2💅2
Детерминированность окружения

С этой взрослой жизнью и взрослыми делами совсем не получается выделить время на проект 😭 Но дела рано или поздно заканчиваются, и часок-другой я все равно стараюсь найти)

Во-первых, ¡Hola! всем, кто меня читает, и muchas gracias! 👋

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

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

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

Как решить?
Я пришла только к одному решению, которое будет работать всегда: считать позицию объектов окружения только в пространстве вокселей, причем всегда в LOD0. Это означает, что необходимо "догенеривать" воксели для чанков, у которых LOD выше 0. Ну, что ж, это плата за детерминированность. 🧂

На данный момент тестирую этот подход, посмотрим чуть позже, что получится 😶

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
👍165👏21🔥1
Иии, всем привет! 💃

Наверное многие уже решили, что я забыла про канал и больше не будет постов 🫥 Спешу обрадовать - это не так! 🥔

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

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

Всех с наступающими праздниками и хорошего начала года! 🥰
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥26🎄166❤‍🔥2💋1
Всем привет! 💃

Я вернулась к коду, и первое, что я поняла: как же сложно вспоминать, на чем остановилась, спустя несколько месяцев! 🔥

Но ничего, свежий взгляд, многое становится более явным, заодно какая никакая, но проверка временем 🥔 Некоторые решения в коде теперь кажутся какими-то…странными что ли? 😛

Как вы помните, и как я вспомнила, я остановилась на проверке варианта «догенерации» вокселей в биоме по требованию, чтобы можно было правильно посчитать положение объектов на ландшафте. Самая большая проблема в том, что там много-много unsafe кода, и часть даже не обернуто во что-то более понятное 😤

Ах, сама виновата 🧂

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥25😁87💯5🆒3
Всем привет! 🥰

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

Так вот, давайте представим, что мы запускаем какую-то параллельную джобу (IJobFor). Нуу, допустим, 1000 раз:
var jobHandle = job.ScheduleParallel(1000, 1, default);


Причем, мы хотим, чтобы вызовы Execute у нас не батчились, поэтому ставим циферку 1 вторым аргументом.

И что же я вижу в Profiler Analyzer? Count 15? И как это считать?🤔

Ваши идеи? 🚪
Please open Telegram to view this post
VIEW IN TELEGRAM
🦄75🤔41❤‍🔥1