Unity Architect: архитектура unity проектов

Unity Architect: архитектура unity проектов

@uniarchitect

Пишу о том, что нельзя нагуглить про архитектуру, разработку и пр.Мой курс по архитектуре: https://course.uniarchitect.dev/y/9b8ec0cИногда выкладываю видео и веду стримы: youtube.com/@vangogihПо всем вопросам: @vangogih

5 272подписчиков
Ежемесячно🇷🇺

Похожие каналы

Все →

Последние посты

Unity Architect: архитектура unity проектов — пост в ТГ канале

MENUITEMИз проекта в проект прихожу и вижу одну и ту же картину.Есть маленькие полезные скрипты, которые упрощают работу, но все они запрятаны в глубине проекта.О чем речь:— Открыть Persistent Data Path в проводнике— Переключить сцену, чтобы не искать её в иерархии— Удалить закешированные данные— Переключить редактор из dev в prod или qaИ прочие мелочи, которые нужно часто вызывать в редакторе.Обычно для этого создаётся скрипт с атрибутом [MenuItem("Tools/...")].🔸ПроблемаПочему-то этот полезный код очень любят разбрасывать по скриптам, папкам, сборкам.Сторонние плагины туда же — Odin, DoTween и прочие имеют свои секции в Tools.Поиск нужной кнопки начинает отнимать время.Помножь на количество рабочих дней — получишь кучу времени потраченного на поиск.При этом не все команды пишут логи, и найти откуда именно этот код вызывается — бесящий процесс.В момент поиска не делается ничего полезного, ты просто ищешь ответ на вопрос "где это лежит".Мелочь, но дико бесит 😵🔸РешениеВсего 3 пункта:1️⃣ Далем Editor asmdef в проекте: GenshinImpact.Editor2️⃣ Все пути кладутся в 1 файл с константами, который лежит в корне:public static class ToolConstants { public const string Root = "Silverfox"; public static class Build { public const string Prod = Root + "/Build/Prod"; }}3️⃣ При создании tool'а в качестве корня — имя проекта или компании: [MenuItem("Silverfox/Clean local data")]Итого получаем в коде: [MenuItem(ToolConstants.Build.Prod)]Т.е. путь до нужного кода — два шага: поиск по имени компании, а до других элементов легко дотянуться через файл с константами.🔸Почему это работает▫️ Не нужно держать в голове иерархию сборок. Достаточно найти строку Silverfox" — и ты сразу в файле со всеми tool'зами▫️ Можно быстро прикинуть иерархию и понять как добавить или поправить tool. Особенно это полезно для новичков в проекте.▫️ Быстрее чем спрашивать AI — переключение контекста и формулировка вопроса медленнее чем Ctrl+Shift+F в IDE🔻 Простое соглашение — один файл, один к

11 апр. 2026 г.2 960В Telegram

UNITEXTTextMeshPro — это покупка 2017 года, которую Unity встроила и с тех пор поддерживала на плаву, исправляя баги.Я не гуру нюансов отрисовки текста, но я никогда и не задумывался что TMP, по стандарту Unicode, не способен отобразить все многообразие символов правильно 😱Я решил разобраться подробнее в различиях и фичах, чтобы понять в чем инновационность UniText.🔸ЭмодзиЧтобы показать эмодзи в TMP, тебе нужно: создать текстурный атлас со спрайтами, импортировать его, разметить каждый спрайт, привязать к компоненту.И всё равно ты получишь статичную картинку без поддержки Zero Width Joiner (семьи, флаги, тона кожи).В UniText ты просто пишешь "Привет! 👋🏽" — и оно работает. Эмодзи берутся нативно с каждой платформы: Segoe на Windows, Apple Color Emoji на iOS, NotoColorEmoji на Android/Linux.Мне смешно об этом писать, но теперь emoji просто есть и не нужно костылить fallback шрифт в новых версиях и свой атлас emoji в старых версиях TMP.🔸RTL и смешанный текстАрабский, иврит, урду, фарси — ни одно решение в Unity не реализует Bidirectional алгоритм по спецификации Unicode.Костыль вроде RTLTMPro покрывает базовый кейс, но ломается на смешанном тексте — когда в одной строке арабский и английский.Правильное отображение смешанного текста — это не просто "перевернуть строку".В Unicode разработали для этого целую спецификацию UAX #9 с 861 тысячей тестов. Каждый тест — конкретная комбинация символов разных направлений и ожидаемый порядок отображения.Проходит все тесты — текст корректен в любой комбинации языков.UniText проходит их все:▫️ Bidirectional (направление текста)▫️ Line Breaking (где можно переносить строку)▫️ Grapheme Clusters (что считать одним "символом" — важно для эмодзи и составных букв)TMP ничего из этого не проходит на 100% 🫠Т.е. нет гарантий что чат в вашей игре будет правильно показывать что пользователь написал.🔸Шрифты без боли1️⃣ TMP растеризует глифы оффлайн в редакторе и сериализует атласы на диск.Отсюда грязные файлы в git, конфликты при мёрже, р

6 апр. 2026 г.3 670В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

ADR: ФИКСАЦИЯ АРХИТЕКТУРНЫХ РЕШЕНИЙДостаточно часто находил у себя и видел у других огромное желание, при присоединении к новому проекту, предложить улучшение или постараться исправить уже имеющуюся систему.Это нормально, мы понимаем и видим как можно сделать лучше, наш глаз не замылен и мы стремимся поскорее с головой ворваться в новый проект.Вот только один момент мы не учиваем: "А почему это сделано именно так и почему это никто не спешит исправить?".Можно, конечно, все объяснить простым конформизмом и ленью, но чаще всего мы упускаем одну простую мысль.Когда-то уже кто-то взял ответственность и принял решение.Не принимать решение - это тоже решение.И получается что прежде чем предложить изменение, нужно понять контекст текущего решения. А чтобы потом кто-то такой же смелый не переписал уже твоё — этот контекст нужно зафиксировать.🔸Проблема: устные договорённостиКлассический сценарий: обсуждаете с командой, как лучше встроить новый модуль. В чате или на созвоне находите оптимальное решение, все соглашаются — но ничто не фиксируется письменно.Через две недели часть команды уже не помнит деталей обсуждения, другие уверены, что договорились о другом, а новый участник не понимает причины выбора.В итоге любое устное или не зафиксированное решение будет пересматриваться и, скорее всего, переписываться заново — просто потому, что отсутствует общий ориентир.А как мы знаем, архитектура — это набор ключевых решений. Но решения без зафиксированного контекста — просто факты без объяснения.🔸ADR: форматВ 2011 Michael Nygard предложил формат Architecture Decision Records (ADR).Формат минимален:▫️ Status — proposed, accepted, deprecated, superseded▫️ Context — какая ситуация и ограничения привели к решению▫️ Decision — что именно решили▫️ Consequences — что из этого следует, включая негативные эффекты🔹Ключевое: ADR фиксирует не "что мы сделали", а "почему мы так решили".🔸Правила ведения▫️Каждый документ включает только одно решение▫️Информация из ADR при изменениях не удаляе

1 апр. 2026 г.3 370В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

ПРОЕКТИРОВАНИЕ: КОМПОНЕНТЫСлово "компонент" — одно из самых перегруженных в разработке. В Unity это MonoBehaviour, в ECS — struct с данными, в пакетном менеджере — package.В модели C4 — совершенно другое.Много раз видел как разработчики рисуют схемы, добавляя на одну диаграмму и крупные подсистемы (UI, Networking, Analytics), и конкретные классы внутри них.Всё на одном листе, без разделения по масштабу.Результат — схема, которую понимает только автор.И вот в чём причина. Между уровнем контейнеров ("что мы деплоим") и уровнем кода ("какие классы пишем") — пропасть.Контейнеры слишком крупные чтобы по ним начинать имплементацию. Классы слишком мелкие чтобы по ним планировать.Без промежуточного уровня разработчик вынужден мешать оба на одной схеме. Отсюда каша.🔸Что такое компонент в C4Компонент в модели C4 — это группа связанной функциональности за чётким интерфейсом (API, модель, фасад). Не один класс, не файл — а логическая единица (чаще папка), выделенная из кода по ответственности.Компонент:▫️ Живёт внутри контейнера▫️ НЕ деплоится отдельно — деплоится контейнер▫️ Все компоненты одного контейнера выполняются в одном процессеВ Unity-проекте ближайшая аналогия — внутренняя структура asmdef: из каких подсистем она состоит.Но маппинг не 1:1 — один компонент может быть размазан по нескольким asmdef, а одна asmdef может содержать несколько компонентов.❗️ Уровень компонентов и Unity-компоненты (MonoBehaviour/IComponentData) — абсолютно разные, не связанные понятия.🔸Пример: Unity-клиентВ статье про контейнеры мы установили — Unity-клиент это монолит, 1 деплоемый unit. Но внутри этого монолита есть структура.В типичном проекте есть инфраструктурный слой, который очевиден:— UI, Networking, Assets, Analytics, SaveНо ценность уровня компонентов проявляется в декомпозиции игровой логики. Именно тут начинаются вопросы:▫️ Battle System — боевая механика, расчёт урона, управление раундами▫️ Meta Game — прогрессия, апгрейды, разблокировки▫️ Social — кланы, чат, друзья, лидерборды▫

16 мар. 2026 г.3 640В Telegram

CORECLR АНОНС АЛЬФЫПару дней назад на GDC Unity анонсировала Alpha релиз CoreCLR в Unity.Странно, но почему-то новость не встретила большого хайпа и бурного обсуждения.Наверное, потому что это, пока, все еще обещание, а не фактический релиз.Более того, новость Unity пока опубликовали в виде короткого shorts на youtube.Для тех, кто вдруг пропустил, я написал 3 подробных поста сравнения основных отличий и преимуществ, что нам даст CoreCLR:▫️CoreCLR в Unity — это круто▫️CoreCLR vs Mono▫️CoreCLR vs IL2CPP🔸Что мы узнали нового:1️⃣ Alpha релиз будет в версии 6.8 позже в этом годуНу, как говорится: "Могу только поставить 🕯 и верить, что в этот раз версия и сроки не будут сдвинуты".А если серьезно, то назначение конкретного номера версии — это уже коммитмент по срокам.🔻Мой прогноз:6.8 точно не LTS, а значит, это tech release. 6.4а и 6.5а (текущие tech release) были выпущены в Октябре-Декабре. Ожидаю, что 6.8a появится с Сентября по Декабрь 2026.2️⃣ У нас будет .NET 10 и C# 14И тут сюрприз — ожидал максимум .NET 8, а получили сразу десятку.Поддержка именно последней версии .NET и C# говорит о том, что маловероятно это будет fork .NET с фиксами, как это было с Mono.Что, безусловно, радует — возможно, будем регулярно получать свежие версии .NET в Unity.3️⃣ Прощай Domain Reload и MonoНу, тут лишь подтверждение моего прогноза из поста CoreCLR vs Mono:Время Domain Reload снизится минимум на 75%. В моём примере — с 12 секунд до 3. Останутся только вызовы Awake/Destroy и десериализация состояния сцен.Технически, именно Domain Reload и правда уйдет в небытие как термин. Т.к. мы будем выгружать не весь домен, а лишь перекомпилированные assembly.Потому просто жду переименования Domain в Assembly Reload (или что-то около).Это и правда уберет примерно 75% времени, но вот избавиться от вызовов Awake/Destroy/InitializeOnLoad, а также полного сброса состояния сцены и редактора, мне кажется, что не получится.Так что прогноз все еще валидный, ждем релиза и замеров 😊4️⃣ Полный переход на

12 мар. 2026 г.3 990В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

ПРОЕКТИРОВАНИЕ: ТРЕБОВАНИЯВ прошлой статье мы разобрали исследование, где 43 из 68 работ указали на размытые требования как корень неверной оценки сроков.И пообещал разобрать — что конкретно должно быть в документе, чтобы не влетать в бесконечные доработки.Давайте на чистоту. Мы не так часто вносим правки в геймдизайн документы.Получил GDD — сел делать. А потом неделя за неделей всплывают кейсы, которые никто не описал. Вот оно, расширение сроков.🔸Функциональные требованияПо IEEE 1471-2000 (это то самое определение архитектуры ПО по стандарту), у стейкхолдеров есть viewpoint — видение того, как система должна работать. На практике этот viewpoint и есть GDD.Уже из него программисты должны формировать architectural description (AD) — техническую документацию по сути. В геймдеве AD почти никто не делает, потому все обычно прописывается в GDD (viewpoint).Хороший GDD содержит:▫️Функциональное описание механик▫️Визуальное видение: мокапы, скетчи, референсы▫️Краевые случаи▫️Пользовательские истории🔸User Stories — лучший форматПользовательские истории — описание требований с точки зрения пользователя, а не внутренней реализации. Вместо "выдаем награду при окончании боя" — "если бой окончен, то я вижу экран награды".Почему это работает:▪️Иерархическая структура "если … то …" один в один ложится в код▪️QA берет документ и сразу получает список кейсов для проверки▪️Легко инвертировать: "а что если НЕ?" — и ты находишь пропущенные краевые случаиОни делятся на два типа:▫️Happy path — основной поток без ошибок▫️Alternative path — что происходит когда что-то пошло не такПример:— Happy: если я нажму кнопку "Купить", я увижу подтверждение покупки— Alt 1: если у меня недостаточно валюты, я увижу предложение пополнить баланс— Alt 2: если во время покупки пропал интернет, я увижу сообщение об ошибке и мой баланс не изменитсяHappy path прямолинеен и понятен. А вот устойчивые системы отличаются проработкой alternative path.Именно на них тратится 80% усилий и именно они формируют стабил

27 февр. 2026 г.4 080В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

ASSET BUNDLES ПО КИРПИЧИКАМС Октября 2024 по Июль 2025 я вёл курс по архитектуре. 1-2 раза в неделю, по полтора-два часа. 40 человек. Перед этим полгода собирал и прорабатывал материал.Во время ведения курса я пообещал ребятам дополнительное занятие — глубокое погружение во внутреннее устройство Unity.Не "как пользоваться API", а как оно работает изнутри, на уровне исходников.Первым таким занятием стала система компиляции: Bee, Tundra, Domain Reload. Где не просто разобрал теорию — написал программу, которая компилирует скрипты без самой Unity 🛞Занятие было записано и выложено в закрытую группу вместе со всеми материалами: исходники, текстовые разборы — всё, что было нарыто в процессе подготовки. Всегда под рукой, чтобы в любой момент вернуться и вспомнить детали.Меня очень удивило и порадовало что 10 человек из группы попросили провести ещё одно такое занятие.Тему выбрали сами: Asset Bundles.Я подумал: Вдруг кому-то ещё в блоге будет интересно разобраться в том, как на самом деле устроен этот механизм?И решил что хочу попробовать такой формат активности в блоге 😊🔸Что будем разбиратьНикакой воды и общей информации из документации.Мы полезем в исходники и по кирпичикам разберём:▫️ Формат архива UnityFS — побайтово: заголовок, таблица блоков, директория файлов▫️ Сериализация и TypeTree — как Unity сериализует объекты внутри бандла, что такое PPtr▫️ Компрессия — LZ4 vs LZMA на уровне кода: почему LZ4 даёт random access, а LZMA нет▫️ Пайплайн загрузки — полный путь от вызова LoadFromFile до готового AssetBundle▫️ Пайплайн выгрузки — batch-удаление, освобождение хэндлов, очистка хранилища▫️ Платформозависимость — почему бандл для Android не загрузится на iOS▫️ Загрузка ассетов — как LoadAsset строит граф зависимостей между бандлами▫️ Патчинг и рекомпрессия — hot swap бандлов без потери C# ссылок🔸Формат— 28 февраля, 14:00 МСК— Онлайн в Zoom— После занятия в закрытую Telegram группу будут выложены: запись, текстовые материалы и исходный код программ-примеров— Доступ к

23 февр. 2026 г.4 070В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

МАШИНА СОСТОЯНИЙ - АДищеМашина состояний — один из самых интуитивно понятных подходов. Нарисовал квадратики, провёл стрелочки, описал условия переходов — готово.И если для анимаций, поведения противников, состояний предметов и квестов — использование оправдано и обосновано.То когда состояния начинают просачиваться в глобальное управление — подключениями, сценами, окнами UI — появляется проблема.Ты не сможешь продумать все возможные события и условия переходов. Рано или поздно это приведёт к зависанию в одном состоянии машины.Дийкстра рассуждал об этом ещё в 68 году — описывая:В мультипрограммных системах, где несколько процессов работают параллельно с неопределённым порядком прерываний, возникают часто ошибки невоспроизводимые — зависящие от случайного момента прерывания.Чуть более простым языком эту проблему можно описать так:Событие, поступившее конечному автомату в некотором контексте, может не вызвать никакого действия, поскольку автомат не в состоянии однозначно определить, какое именно действие должно быть выполнено, исходя из полученного входного сигнала и текущего состояния машины.🔸Пример 1: LoadingСцена Loading — инициализация, подключение к серверу, скачивание конфигов.Следующее состояние — Meta, главное меню.Переход Loading → Meta срабатывает по условию: «все конфиги загружены и соединение активно».Пользователь во время скачивания свернул приложение чтобы прочитать новый пост по архитектуре 😎 и вернулся через 10 минут. Соединение отвалилось по таймауту, часть конфигов скачалась, часть — нет.Приложение получает OnApplicationPause(false) — «пользователь вернулся». Машина всё ещё в Loading. Но конфиги не все, а соединение мертво.Перехода «переподключиться» не предусмотрено, потому что автор не заложил комбинацию «Loading + потеря соединения + частичная загрузка + выход из паузы».Событие пришло, а ни один переход не сработал — игра зависла в Loading навсегда.🔹Пример 2: ПаузаЦепочка уровней и игровой цикл: открыл уровень → бой → противники убиты → сбор нагр

22 февр. 2026 г.3 800В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

ПРИЧИНА ПРОВАЛА ПРОЕКТОВВ Magic Battle Arena мы с партнером привлекли pre-seed раунд с runway на 1 год 2 месяца. Я уже рассказывал об этом: раз, два, триДумали — хватит. Рассчитывали 8 месяцев на MVP, 4 месяца на итерации.По факту 4 месяцев хватило только начать улучшать метрики. Нужно было runway минимум в 2 раза больше.Неверная оценка сроков стала краеугольной ошибкой, которая привела к закрытию компании.А вот смотрите что говорит наука.🔸Исследование 2019 года: качество кода не при чемВ 2019 году исследователи проанализировали 2171 публикацию с 1990 по 2017 год по теме провала ПО. Из них отобрали 68 наиболее релевантных и тщательно изучили.Задача: выявить и ранжировать факторы провала IT проектов.Как думаете, насколько техническое качество кода оказалось важным? 🤓Insignificant — ничтожно малым. Из 13 выявленных факторов technology illiteracy попала в самый низ.А вот главный фактор:▫️ Wrong estimation of time and cost — неверная оценка времени и стоимости▫️ 43 из 68 исследований указали на это как основную причину провала🔸Другое исследование: откуда берется неверная оценка?Исследователи из Aalto University в 2014 году провели анализ корневых причин 4 случаев провала в продуктовых компаниях. Для каждого кейса строили диаграмму причинно-следственных связей — от 130 до 185 причин.Три основные связи повторялись в 3 из 4 кейсов:▫️ Weak Task Backlog — расплывчатые требования, неверные приоритеты▫️ Lack of Cooperation — между отделами теряется информация, нужная для реализации и тестирования▫️ Lack of Software Testing Resources — менеджмент недовыделяет ресурсы на тестированиеИ две из трех цепочек как раз проходят через Sales & Requirements. ▫️Расплывчатые спецификации → слабый backlog → неверные приоритеты. ▫️Недостаток коммуникации → потеря информации → разработчики и тестировщики не понимают что делать.Требования — точка, где теряется критическая информация.🔹На Combat Quest я это ощутил на себе.Настраивал процессы с нуля. В GD-документах постоянно пропускали краевы

6 февр. 2026 г.4 260В Telegram
Unity Architect: архитектура unity проектов — пост в ТГ канале

CORECLR VS IL2CPPЭто последняя статья из цикла: "CoreCLR - это круто", где я стараюсь рассказать про основные, важные изменения, которые CoreCLR может превнести.Предыдущие статьи: раз, два.На этот раз поговорим про различия в runtime'ах, которые непосредственно исполняются на пользовательских девайсах (а не в редакторе, как в прошлых статьях).🔸VTableКогда вызываешь виртуальный метод, runtime должен понять какой именно код исполнить.У базового класса и наследника методы разные, но вызов 📞 выглядит одинаково.VTable — это массив указателей на методы. Каждый тип хранит свою таблицу.Вызов виртуального метода = взять указатель из таблицы по номеру слота и сделать jmp на значение указателя в слоте.🔸Где IL2CPP добавляет работыВ CoreCLR vtable — просто массив указателей на код. 8 байт на слот.В IL2CPP каждый слот содержит ДВА указателя: на код и на метаданные. 16 байт.Зачем? IL2CPP — это AOT. Нет JIT, который достроил бы информацию в runtime. Всё предсгенерировано заранее.Но главное размер. CoreCLR разделяет информацию о типе на "горячую" (MethodTable — только для исполнения) и "холодную" (EEClass: reflection, interop).При виртуальном вызове CPU загружает в кэш только MethodTable.IL2CPP держит всё в одной Il2CppClass — 200+ байт.При частых вызовах методов разных типов процессор постоянно выгружает одни данные из кэша и загружает другие.Отсюда и сложно писать производительный код без Burst: ты теряешь контроль над тем, что по факту у тебя исполняется на устройстве 😬🔸Interface Dispatch — тут разница огромнаяИнтерфейсы сложнее классов. Один тип может реализовать много интерфейсов, и runtime должен найти нужную реализацию по указателю на интерфейс.IL2CPP хранит массив interfaceOffsets — пары "указатель на интерфейс + смещение в vtable".При каждом вызове метода интерфейса il2cpp идёт циклом по этому массиву, сравнивая указатели: if (interfaceOffsets[i].interfaceType == declaringInterface)Линейный поиск короче.Можешь посмотреть сам, файл: ClassInlines.h в исходниках il2cpp.Т.

3 февр. 2026 г.3 570В Telegram