Unity Architect: архитектура unity проектов
4.98K subscribers
17 photos
1 video
79 links
Авторский блог unity lead'a. Пишу про архитектуру проектов и свой путь.

Мой курс по архитектуре: https://vangogih.notion.site/cb0f15e57d5a4f10b2a7df9664b8e5f9

Иногда выкладываю видео и веду стримы: youtube.com/@vangogih

По всем вопросам: @vangogih
Download Telegram
(А|а)рхитектура

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


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

🔸И начнем мы с определения от Мартина Фаулера:
Architecture is about the important stuff. Whatever that is.

Архитектура — это про самое важное. Что бы это ни было.
Who Needs an Architect?

Черт, Мартин... Отдаю должное тебе за вклад и работу, но кажется, что с высоты твоего опыта, в дело вступило проклятие знаний.
И такое определение больше запутывает, нежели отвечает на вопросы 😐

🔸Благо университет Carnegie Mellon в 2017 году выпустил статью What is your definition of software architecture?, из которой мы сможем проанализировать несколько определений и выделить в них ключевое.

Начнем с стандарта IEEE:
Архитектура определяется как фундаментальная организация системы, выраженная через её компоненты, их взаимоотношения друг с другом и с окружающей средой, а также принципы, управляющие её дизайном и развитием.
DOI: 10.1109/IEEESTD.2000.91944

Стандарт не был бы таковым, если бы предлагал лишь один абзац.
Он так же связывает понятие архитектуры с заказчиком, его видением и того как создаются требования (см. картинку прикрепленную к посту)

Если наберем 💯 реакций, я разберу стандарт подробно в отдельной статье 😎

🔸Интересное определение предлагает нам Rational Unified Process:
Архитектура — это набор ключевых решений об организации системы, её структурных элементов, интерфейсов, поведения и их объединения в подсистемы, определяемый выбранным стилем.

🔸Следующее определение предложил создатель модели COCOMO:
Архитектура программной системы включает в себя:
Набор программных и системных компонентов, соединений и ограничений.
Набор требований заинтересованных сторон системы.
Обоснование, показывающее, что компоненты, соединения и ограничения определяют систему, которая при реализации удовлетворит требования заинтересованных сторон.
Barry Boehm


И у всех этих определений, которые предложены в разные время разными людьми есть кое что общее:
🔹Архитектура — это набор ключевых решений и ограничений
🔹Решения и ограничения должны удовлетворять требованиям заинтересованных сторон
🔹Решения и ограничения определяют организацию системы
🔹Система выражается через компоненты и способы связи между ними

И мы можем из этого общего собрать термин, который емко дает всю необходимую информацию и согласован со стандартом:
Архитектура — это принятие ключевых решений, которые удовлетворяют требованиям заинтересованных сторон, о правилах и ограничениях, которые определяют структуру, элементы и способы их связи в системе.


Не хочется раздувать определение, вводя дополнительные комплексные понятия, но я бы еще сделал пометку на полях:
И желательно чтобы эти решения замедляли рост когнитивной сложности проекта 😬


Но в чем точно я не ошибся, когда писал пост полтора года назад, так это в том, что архитектура это далеко не только код!
Но об это по порядку в следующих статьях 🫡

Ты знаешь кому переслать этот пост.
Ставь 👍 если тебе по кайфу такая движуха

#аббревиатуры@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍50💯43
МНОГОСЛОЙНАЯ АРХИТЕКТУРА: ПРEМЬЕРА ВИДЕО

Начинаем через 5 минут, подключайся скорее 🛞

Разберем:
🔸Структуру организации и то как она копируется в структуру проекта
🔸 Как можно представить любую игру на unity в виде слоев
🔸 Пример структуризации проекта моей студии silverfox games

➡️ССЫЛКА НА ПРЕМЬЕРУ

@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🔥2🤯1
АРХИТЕКТУРА НА SCRIPTABLE OBJECT

Я уже как лет 6 регулярно отвечаю на вопросы в архитектурном чатике.
И уже 6 лет туда регулярно залетают вопросы в духе:
— А архитектура на Scriptable Object (SO) норм?
— Посмотрел видеоролик Х и Y, думаю сделать проект на SO, что думаете?
— Хочу систему конфигов сделать через SO, что скажете?


У меня есть один почти загубленный проект богатый опыт использования этого подхода.
Отсюда, 6 причин почему SO, скорее всего, станут занозой на большом проекте.

1️⃣ Изменения в SO отображаются в git только после сохранения проекта.
Оо, сколько раз это ломало проект или делало вас "некомпетентным" в глазах других после заливки новой фичи.

Кейс простой:
— У вас есть 50 SO-объектов.
— В 5 из них вы поменяли значение/ссылку.
— Открыли git, сделали commit.
— У вас всё работает, у других — нет. 😱


У меня, честно, глаз дергается каждый раз, когда я меняю что-то в SO.
Жму по 10 раз Ctrl+S и визуально перепроверяю каждый asset-файл на корректность изменений.

2️⃣ SO-объект сохраняет изменения между запусками.
Легко можно получить ситуацию, когда вы указали ссылку на SO-объект в вашем префабе, изменили значение в runtime' e, и это значение осталось в SO-объекте.

И самое страшное в этом — ссылочные типы:
— Вы передали List<T> из вашего SO как аргумент в метод, в котором добавили/изменили/удалили значение
— Та-дам! После того, как вы выйдете из PlayMode, изменения останутся внутри SO

Вот и получается что вроде все настроил, запустил один раз, все работает.
Запускаешь 2 раз и все... А ведь день так хорошо начался 😬

3️⃣ Из пункта 2 → Вы вынуждены копировать данные из SO, чтобы использовать их в runtime.
Вместо тысячи слов — реальный класс в котором все данные копируются в новый SO объект, чтобы изменять их в runtime'е.

И так почти в каждом SO-объекте:
1000 бесполезных строк кода и 10ки MB бесполезных аллокаций. 😭

4️⃣ SO при создании грузит в память все asset'ы на которые ссылается.
Допустим, вы делаете rogue-like игру:
— В игре 100 уровней == 100 префабов
— Вы создаете SO-объект и добавляете туда все ссылки на префабы
— Прокидываете ссылку с SO в объект на сцене
— Запускаете игру и все префабы, на которые указывает ваш SO, успешно загружаются в RAM устройства 😱

Вам нужен один уровень, а в памяти все 100.

5️⃣ Вместе с SO вы тянете нативную часть.
Внутри SO будут вызваны методы, которые являются частью unity.

И этот объект будет дороже в создании как по памяти, так и по производительности.
А также он будет иметь хроническую проблему сравнения с null.

6️⃣ Удаление SO-объекта не показывает файлы, которые ссылались на него.
Как результат, ищи-свищи, в каком из SO-объектов потеряна ссылка. 🫠

А по факту, никто просто не удаляет SO-объекты из проекта, так как это очень багоопасно.
Просто делают новую конфигурацию, что захламляет проект.

Единственное решение:
Через глобальный поиск искать guid файла, который был удалён, во всех *.asset'ах проекта. 😵

🔻Отсюда правила, которые я ввожу на своих проектах, чтобы избежать проблем выше:
🔸Прямые ссылки на SO запрещены.
Только путь до asset'а , либо AssetReference (если есть Addressables).
🔸Любая вложенность SO→SO, Prefab→SO запрещена (если нужна, см. пункт выше).
🔸В SO никакой логики: максимум Pure-методы и get only-свойства.
🔸Ссылки на любые коллекции должны возвращать только IReadOnly*<T> интерфейс.

Итого:
Easy to learn, hard to master.
Для маленьких проектов/прототипов еще может быть.
Для работы в большой команде, кмк, слишком много нюансов, чтобы использовать это как архитектурную основу проекта 🫠

Ну и я там продажи на свой курс снова открыл.
Уже 15 лекций провёл, кучу отзывов собрал.
Ещё около 20 лекций впереди.
Залетай:
https://payment.silverfox.games/

Сохраняй этот пост себе и пересылай коллегам, чтобы держать эти нюансы всегда под рукой. 😎
Ну и делись своим опытом в комментах💪
Ставь 👍, если тебе по кайфу такая движуха!

#проект_в_разработке@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍49🤮20🔥10🤪2💩1
КОДОГЕНЕРАЦИЯ

Фича, которая реже всего встречается на проектах, где я работал.

Что странно, ведь это очень эффективный инструмент с очень высоким отношением затрат и результата, и вот почему:

1️⃣ Единственный способ увеличить продуктивность программистов — использовать кодогенерацию.

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

2️⃣ Вы тратите время только на поддержку кодогенератора, а не кода, который он генерирует.

Если в сгенерированном коде баг — исправляем генератор, а не все объекты, что он создал.
Такая же логика работает для всего, что генератор создает.

Т.е. в сравнении имплементации с кодогенерацией и без, поддерживать нужно будет меньше кода.

3️⃣ Это очень легко.
Чем отличается генерация JSON-файла от генерации скрипта?
— Вообще ничем. Любой класс — это текст внутри файла.
Компилятор увидит эти файлы, сотворит магию (нет) и код будет готов к использованию.

Вот крутой пример из самого популярного DI-контейнера для Unity (всего 90 строк кода 🤯).
Никаких хаков и продвинутого понимания языка. Просто код, который генерирует код 😅

4️⃣ Это может быть очень быстро.
Вместо использования рефлексии можно сгенерировать код, который будет вызывать нужные методы напрямую.

Из популярного:
🔸Операции (де-)сериализации
Например, тот же Newtonsoft.Json использует IL Weaving для генерации IL-кода, который преобразует строку в объект во время исполнения программы.

В unity же значение в каждый из элементов объекта проставляется через рефлексию.
Жду реализации через SourceGenerator'ы 🛞

🔸Генерация Data Transfer Object'ов
Для общения клиента и сервера, вместо того чтобы писать объекты для данных вручную, можно их полностью генерировать.
Безусловно, такая фича уже давно есть в Swagger и много где еще, но в игровых проектах я все равно встречаю такое редко.

Чаще генерация происходит через первый сайт в google'е 🫠

🔸 Связь с нативной частью Unity.
Нап
ример, перехват событий из Animation Event можно полностью сгенерировать.
Тем самым избежав типичных: "Ой, эффект на персонаже X перестал работать, посмотри чо там 🥺".

Мы этот подход использовали на проекте Magic Battle Arena и полностью генерировали из имен fbx-объектов:
🔹 События анимации, которые вызывали нужный метод в коде
🔹 Уникальные типы анимации для каждого персонажа.
Каждый персонаж — свой enum, который всегда консистентен с анимациями, которые на нем есть.
🔹 Настройки для художников спецэффектов.
Добавил fbx, нажал одну кнопку, настройки со всеми типами анимации готовы за 1 секунду.

5️⃣ Можно генерировать целые фичи.
На Magic Battle Arena мы генерировали DTO, (де-)маршалинг данных и Memory Pool для всех этих объектов 😎

Т.е. по сути весь транспортный слой, отвечающий за коммуникацию клиента и сервера, полностью кодогенерировался.
Мы использовали T4 Templates. До сих пор очень мощный и крутой инструмент 🫡

Итого:
Лично для себя не вижу ни одного повода чтобы не задавать себе каждый раз перед написанием новой фичи:
"А могу ли я какую-то часть накодогенить?"🤔
Так шаг за шагом и проект сам себя рано или поздно напишет 🤣

🔻Давайте соберем маленькую базу мест, где еще кодоген будет полезен.
Расскажите в комментах, где вы используете(-али) кодоген и он сослужил вам верную службу 🫡

Ты знаешь кому переслать этот пост.
Ставь 👍 если тебе по кайфу такая движуха

#проект_в_разработке@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥39👍275😁2
Почему я сделал курс по архитектуре проектов в Unity?

Потому что вижу дикий разрыв между «учебными» рассказами о том, как делать проект, и тем, как всё происходит в реальности.

Этот разрыв настолько большой, что приходится чуть ли не полностью забывать то, чему учат, и делать всё по-другому, когда речь идёт о настоящей командной разработке игр 🤓

Почему так? Есть несколько причин:

1️⃣ Требования при одиночной и командной разработке — это разные миры.
Отсюда возникают неочевидные задачи: управление конфигами, совместная работа в Git, настройка staging (dev/prod окружения), аналитика, CI/CD, code review.

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

2️⃣ Проклятие знаний.
Часто, поработав в одном проекте, люди думают: «Ну, все же делают так же».

Кажется, что и рассказывать особо нечего. Но на деле разрыв растёт: новичков и даже мидлов бросают в реальный проект, где всё иначе, и они не понимают, куда попали.

3️⃣ NDA.
Из-за жёстких пунктов о неразглашении с большими штрафами никто не рвётся делиться подробностями процессов и архитектуры. Порой вообще неясно, что можно рассказывать, а что нет.

4️⃣ Нет времени.
В игровых компаниях плотный график фичевой разработки. После работы уже не до статей и видео, у всех своя жизнь, семья. Так что делиться опытными находками просто некогда.

5️⃣ Высокая требовательность к себе и сложность материала.
Тема непростая, хочется делать материалы качественно. Да и негатив или токсичность по поводу «недостаточно глубоко раскрыл» мало кому интересны. Проще не выносить ничего в публичное поле.

🔸В итоге имеем кучу базовых «стартовых» курсов, которые не очень помогают, когда ты переходишь на серьёзный уровень в реальном проекте. Что-то более глубокое приходится буквально выискивать по крупицам — да и то не факт, что найдёшь.

Я думал, что этот разрыв закроют k-syndicate в 2022-м, когда они выпустили свой курс по архитектуре. Но они сместили фокус на создание собственной игровой студии, и вопрос снова остался открытым 😬

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

За весь период с января 2023 по сентябрь 2024 я упорно изучал разные книги, научные статьи, базу знаний по реальным проектам, анализировал личный опыт — всё для того, чтобы этот разрыв хоть немного сократить.

Понимаю, что сейчас кругом агрессивные продажи и курсы с обещаниями «200к за 2 месяца», и многие уже устали от подобного.
Но я действительно хочу делиться наработками и продавать результат своей работы — ведь вкладывал в это уйму сил и времени 🫠

🔻Важный момент:
Я не маркетолог и не собираюсь навязывать курс кому бы то ни было, чтобы не выглядеть в глазах аудитории очередным инфоцыганом.


🔸Буду рассказывать о нём в блоге, стараясь делать это спокойно и без агрессивной рекламы. Если кому-то интересно прокачаться с учётом реальных процессов, подтянуть архитектуру и все эти нюансы командной разработки — милости прошу. Если нет — всё нормально, у меня нет цели загонять туда всех подряд.

Главное, чтобы вы понимали, зачем вообще этот курс появился и почему я считаю нужным его продвигать: в реальности сложных игровых проектов слишком много незакрытых вопросов, и хочется, чтобы люди не прыгали в омут с головой без нормальной подготовки 😵‍💫

Ставь 👍 если тебе по кайфу такая движуха.

#курс@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍131🤮8
КАЧАЕМ ФАЙЛЫ БЫСТРЕЕ НА 30%

Если вы на старте игры качаете более чем 100 файлов, то есть один забавный способ ускорить загрузку до 30%.

Контента в игре у вас много, а размер билда должен быть <150МБ.
Потому часть вы запаковали в 100 Asset Bundle'ов.
А на старте игры качаете их из CDN через Unity Web Request.

В коде это выглядит примерно так:
IEnumerator DownloadAssetBundle(string url, Action<byte[]> onSuccess)
{
using var request = UnityWebRequestAssetBundle.GetAssetBundle(url);
var op = request.SendWebRequest();

while (!op.isDone)
yield return null;
onSuccess?.Invoke(request.downloadHandler.data);
}

Уверен что у каждого в проекте есть похожий кусок.
Есть идеи как его ускорить? 😬

Ответ:
Application.targetFrameRate = 120


Дисклеймер:
Как и всегда, есть нюансы. Перед тем как применять подобное у себя, тщательно изучите ограничения платформ для вашего проекта.

🔸Как так получается?
— Если вы знаете что такое Synchronization Context, то возможно, вы уже догадываетесь в чем дело.
Это специальный класс в dotnet, который представляет из себя очередь delegate'ов на MoveNext (машин состояний), которые будут вызваны в момент когда наше приложение готово продолжить выполнение асинхронного кода.

В unity синхронизация вызывается в UnityEngine.PlayerLoop.Update.ScriptRunDelayedTasks из нативной части, путем вызова статического метода UnitySynchronizationContext.ExecuteTasks.

🔸Или проще говоря:
— Все продолжения ваших асинхронных операций длиннее одного кадра будут вызваны на следующий кадр в Update.ScriptRunDelayedTasks фазе.

🔸Риторический вопрос:
Действительно ли время загрузки файлов по сети привязано к длине кадра?
— Вообще нет. Установление соединения и скачивание идет в другом потоке в нативной части.

Но вот результаты и обновление состояний синхронизированы с основным потоком и происходят в UnityEngine.PlayerLoop.EarlyUpdate.UnityWebRequestUpdate.

🔸Это значит:
Что если файл качается 45ms, а ваша игра работает при 30FPS, то ~15ms данные будут ждать синхронизации.
Того самого вызова MoveNext для вашего метода DownloadAssetBundle.

Т.е. данные в памяти в нативной части будут через 45ms, но у себя вы их получите только через 66ms.
И буст (местами до 30%) можно получить как раз за счет снижения времени "простоя" данных в ожидании вызова нужной фазы PlayerLoop'а.

Это тот забавный случай, когда магическая строчка в одном месте почему-то дает ощутимый результат 🤣
Так что, как идею, берите на вооружение увеличение FPS на время загрузки и возвращение его в нормальное значение после 😅

❗️Но блин, ребят, это не silver bullet. Проверяйте последствия на своих проектах.
На слабых девайсах это может только сделать хуже.

Если интересно копнуть больше в эту тему, рекомендую посмотреть видео с конференции CLRium.
CLRium #6: Контексты синхронизации (SynchronizationContext)

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

Ставь 👍 если тебе по кайфу такая движуха.

#будни@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍109🔥10
MV*

Сколько копий сломано об эту тему...

Давайте по порядку:
— В 1974-79 годах Trygve M. H. Reenskaug (автор MVC) работал над портативным компьютером "для детей всех возрастов" Dynabook в компании XEROX.
— Именно тогда/там закладывались основы графического интерфейса, формировалось понятие "дружелюбного интерфейса".
— В те же года была и опубликована короткая заметка про разделение на model/view/editor, которая позже преобразовалась в MVC.

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

Давайте попробуем распутать этот клубок, проанализировав первоисточники:

🔸Model:
Модели представляют знания. Модель может быть одиночным объектом (что не очень интересно) или структурой из нескольких объектов.
Между моделью и ее частями, с одной стороны, и представляемым миром, как его воспринимает владелец модели, с другой стороны, должна быть однозначная связь.
MODELS - VIEWS - CONTROLLERS

1. Model — это функциональность, которая возникает при комбинации нескольких систем.
Т.е. это модуль/объект, который вбирает в себя необходимые сервисы системы и использует их для формирования функциональности необходимой для controller/view.

2. Model это не данные, а исключительно интерфейсы/объекты-посредники/фильтры, обеспечивающие удобный доступ к данным, которые могут находится где угодно.

🔸View:
View — это визуальное отображение своей модели. Обычно оно подчеркивает определенные атрибуты модели и скрывает другие, действуя как фильтр.
Представление привязано к своей модели (или ее части) и получает необходимые данные для отображения, запрашивая их у модели.
The original MVC reports

Вспомните пост про ПОРТЫ И АДАПТЕРЫ и представьте что вы пишете код, которые раскрашивает пискели на экране 50 лет назад 😬

Вам придется написать огромный пласт прежде чем вывести Hello World на экран:
— Данные из порта пришли в один из сервисов системы, обработались и готовы к использованию в model.
— View, подписавшись на callback от операционной системы, получила и обработала нажатие на кнопку и вызвала соответствующую часть model.

И как раз для отделения кода связанного с рендером "нужного цвета пикселя в нужном окне на экране" с бизнес-логикой и была выделена view.

🔸Controller:
Контроллер — это связующее звено между пользователем и системой. Он обеспечивает средства для вывода пользовательских команд, предлагая меню или другие способы ввода команд и данных, переводит их в соответствующие сообщения и передает эти сообщения одному или нескольким представлениям.
MVC XEROX PARC 1978-79

Яблоко раздора, вносящее сумятицу во всю систему...

Вместо 1000 слов и долгих объяснений: controller — это выпадающее меню, появляющееся при нажатии на правую клавишу мыши.

Это то, делает отображение сцены в редакторе из 2D в 3D, отключает ненужные gizmos на экране и дает возможность переключать Move, Rotate, Scale, Transform для объектов.

Логика view и model в таком случае никак не меняется. Меняется лишь настройка отображения, которая необходима пользователю для работы.

Вместо длинных выводов:
“Грамотный” UI в Unity всегда должен состоять из model/view/controller.

Нет. В 99.9% случаев вам вообще не нужен controller.
А иногда вы можете и модель не выделять, используя интерфейс сервисов.

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

❗️Потому что изначальная идея MVC удовлетворяет очень узкому набору требований для разработки первого UI для первого портативного компьютера.

И попытка переноса идеи 1к1 приведет лишь к переусложнению вашего проекта (раз, два).

Если вам интересно узнать больше, рекомендую почитать крутой цикл статей на хабре, где автор еще в 2017 году проделал аналогичное исследование 🫡

Это далеко не все выводы, в одной статье невозможно раскрыть столь большой топик.

Ставь 👍 если тебе по кайфу такая движуха.

#архитектурные_подходы@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8719💯5🔥2
ПРОЕКТИРОВАНИЕ: С ЧЕГО НАЧИНАТЬ

Устроился в Nexters, где сейчас переписываю внутриигровой чат со старой технологии на новую. Проектирую его как отдельный dotnet микросервис и должен встроить в существующую архитектуру.
Впереди согласование с техническим директором, бэкенд-лидом, CTO — защита решений, проектирование, реализация.

И вот смотрите... Многие думают, что архитектура — это архитектура кода. Паттерны, классы, модули. Но это не так.
Когда тебе нужно объяснить команде что и как будем делать, когда сервера еще нет, а решения принимать надо — расписывать детали реализации бессмысленно.

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

🔸Уровень 1: System Context

Любая компания — это система. Набор элементов (отделов, команд, unit'ов), которые взаимодействуют между собой ради глобальной миссии. Для игровой компании — развлечение пользователя.
Для контекста, перечитай (А|а)рхитектура.

На уровне системы нам важно отобразить:
— Пользователя и его способ взаимодействия с системой
— Ключевые элементы, благодаря которым фича будет работать

При этом нас НЕ интересуют детали реализации и конкретные технологии.

🔸Пример: мобильная игра

Общий вопрос для начала:
Кто пользуется системой и что является точкой взаимодействия?

— Пользователь: игрок (Gamer)
— Точка взаимодействия: мобильное приложение (Game)

Какие ключевые элементы обеспечивают работоспособность системы?

У любой игры среднего размера (100к+ скачиваний) есть:

▫️ Tech Monitoring — Firebase Crashlytics, Unity Cloud Diagnostics, Sentry
▫️ Analytics — Google Analytics, Facebook, AppsFlyer
▫️ Game Data Service — админка с доступом к данным пользователя. Обычно своя разработка или MBaaS (Mobile Backend-as-a-Service): Firebase/Unity Cloud Save, AWS Amplify
▫️ Data Storage — хранилище данных пользователя
▫️ CDN — Content Delivery Network для ассетов и конфигов

Из комбинации этих элементов ты можешь собрать архитектуру уровня системы для 99% мобильных игр.

см. картинку или оригинал

🔸Модель C4

Поздравляю, первый уровень модели C4 освоен .

Software System — наивысший уровень абстракции, описывающий нечто, что приносит ценность пользователям.
Это то, что строит одна команда разработки, владеет им, несет ответственность и видит внутреннюю реализацию.
Как правило, граница software system = граница команды.

И вот нюанс... Software System — это НЕ bounded contexts, НЕ product domains, НЕ tribes или squads (организационные единицы Spotify модели).
Это конкретная система, которую нужно встроить в существующий ландшафт. В моем случае — микросервис чата в инфраструктуру компании.

🔻 Минималистичное проектирование начинается с системы, а не с кода. Это экономит время на согласование и избавляет от лишней документации.

Начиная с уровня системы, мы прорабатываем value для пользователей и связи между элементами. Только после этого можно спускаться вниз к деталям.
Иначе можно утонуть в обсуждении паттернов, когда еще не понятно что вообще строим.

Это первая статья серии "Проектирование". Дальше по порядку о каждом слое: контейнеры, компоненты, код.
Угадайте какой из них стоит генерировать, а не проектировать ручками? 😅

Ставь 👍 если тебе заходит такого рода контент!
Ты знаешь кому переслать эту статью 💪

#проектирование@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍87🔥1910🤷‍♂1
Unite 2025

Черт, сколько раз я пытался попасть на Unite. То COVID все отменял, то логистика не складывалась, то работа не отпускала. За 9 лет на Unity — ни разу не был на их главной конференции.

Но в этом году звезды наконец сошлись. Добрые люди раздобыли для меня инвайт на Unite 2025, и что самое крутое — меня не отправляет компания 😊

Это значит никакого "обязательного минимума" от работодателя, никаких отчетов о ROI для бизнеса. Только чистый контент для канала и максимум полезной информации для вас.

🔻19 и 20 Ноября я буду на Unite 2025 в Барселоне, где соберется вся команда Unity и ключевые разработчики индустрии.

Для тех кто будет на конференции — пишите в личку, встретимся офлайн.

Для всех остальных — у меня есть оборудование (микрофон, стабилизатор и телефон), чтобы делать качественные сторис прямо с места событий. Буду рассказывать о докладах, показывать атмосферу, и самое главное — могу задать твои вопросы команде Unity напрямую.

Потому предложение:

🔸 От меня — качественный контент без воды о том как проходит Unite, короткие summary докладов, закулисье конференции + я задам твои вопросы команде Unity и сниму их ответы

🔸 От вас — Boost'ы канала
https://xn--r1a.website/UniArchitect?boost
Чтобы я мог публиковать больше сторис в день (лимит зависит от уровня канала).

Не стесняйтесь boost'ануть по максимуму — это конвертирует фичу телеги во что-то реально полезное для всех 🫡

🔻И самое интересное:

Напиши в комментариях какой вопрос ты бы хотел задать команде Unity. Я соберу самые интересные и постараюсь получить ответы от первоисточника.

Может это будет про будущее DOTS, или про планы по улучшению производительности, или про новые фичи которые ждем годами — пиши что волнует.

Ты знаешь кому переслать этот пост 💪

#unite2025
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥54👍1310😁1
Forwarded from Everyday Unity
In Unity 6 🤯
🔥50🤯18
This media is not supported in your browser
VIEW IN TELEGRAM
CoreCLR в Unity быть

Другой вопрос когда и в каком виде.
У ребят есть планы завозить новый backend постепенно.

Как мне показалось, процесс будет похож на то что мы видели с Burst, Jobs и Entities.
Сначала все вышло в виде preview пакета в который постепенно завозилась новая функциональность в течении ... 4-5 лет, я уже и не помню.

Т.е. ещё раз, если и завезут, то точно постепенно и с постепенной докаткой фичей, совместимости и фиксов.

Что будет с mono не сказали.

Но я бы поставил 100€, что отключать старый backend не будут, как не убрали GameObject'ы заместив их ECS системой.

А что вы думаете, дайте знать в комментариях, а я пойду помучаю подробностями людей из unity 🤓

#unite2025
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍5🤷‍♂4
HTTP/2 в Unity 6.3

Наконец-то 🫡
Первую половину этого года я занимался как раз оптимизацией первой загрузки огромного и старого приложения.

Если коротко, там на старте качалось около 700 ассетов размером от 5kb до 5mb.
Около 150mb в общем.

И основная гипотеза была получении fast win за счет перехода с UnityWebRequest на BestHTTP, который поддерживает http/2.

Основная разница, которая полезна в играх:

1⃣ Размер запроса для мелких запросов меньше. HTTP/2 позволяет переиспользовать одно TLS-соединение для множества HTTP запросов к одному домену. То есть публичный ключ/сертификат и установка сессии TLS происходят один раз, а не для каждого запроса.

2⃣ И второй важный момент - запрос на DNS сервер делается всего 1 раз для одного домена вместо похода каждый раз.

На слайде ребята упомянули улучшение перфа на серверной стороне ... имеет место 100%, но для нас, unity разработчиков, есть хороший повод попробовать принести value в скорости загрузки наших игр 😊

Не уверен, но по секрету, я для unity команды делал закрытый Proof of Concept с тестами скорости загрузки через http/1 и http/2.
И unity приняли эту информацию т.к. цифры оказались убедительными.

Так что есть не иллюзорный шанс, что к появлению этой фичи я приложил руку 🥰
Офигеть ... новый пункт в резюме получается 🤣

#unite2025
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥43👍18🤯55
Оптимизации: рекомендации от Unity

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

Вот текстовая выжимка советов, что рекомендуют сами unity и другие разработчики:

1⃣ Отключайте Domain Reload для более быстрого запуска приложения.

Если есть баги связанные с сохранением старых значений в static переменных, делайте статический метод с атрибутом InitializeOnLoadMethod.

Не забудьте #if UNITY_EDITOR обернуть, иначе сборка билда упададет.

2⃣ Unity постоянно улучшают тулзы для профайлинга, он остановится проще и более информативным.

Чекните свежие версии 6.2, 6.3 (сейчас в бете), они добавили Highlights, которые помечают "долгие" кадры на которые стоит обратить внимание.
https://unity.com/features/profiling

3⃣ Если проект долго компилируется, можно при помощи Compilation Visualizer можно посмотреть порядок и время компиляции каждой asmdef в проекте.

Но скажу честно, сделать что-то с временем компиляции сложно.
Нужно либо значительно снижать количество asmdef в проекте, либо уменьшать количество кода 😅

4⃣ Контролируйте и удаляйте неиспользуемые shader variants и keywords.
Для этого можно использовать UnityDataTools - удобная тулза, которая распаковывает все ассеты из билда.

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

5⃣ Project Auditor станет частью unity.
Это пакет, который анализирует ассеты, код, шейдеры, настройки и подсказывает на что нужно обратить внимание.

Эта тулза изначально была разработана одной из unity команд, которая отвечает за анализ и предоставлению рекомендаций по улучшению проекта.
Такая техническая консультация для пользователей enterprise версий.

Я это к тому что советы и рекомендации, которые вы там увидите, я видел во многих репортах от unity об анализе проектов 😅

Да вот и все, каких-то новых открытий лично для меня не было.
База базовая. Или нет 🤔
Дайте знать в комментариях!

Ставь 👍, если тебе по кайфу такая движуха

#unite2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71🔥16
Ищешь работу?

Я полтора года проработал в компании Datasakura, где работал над:

🔸Cut The Rope Daily: 1M+ скачиваний и фичеринг с Netflix 🤯

🔸Overcrowded: Tycoon: 5M+ скачиваний

Это было отличное время, когда тебе как специалисту доверяют и не мучают кучей созвонов и бюрократией.

И сейчас они к себе набирают сильных, самостоятельных и ответственных unity разработчиков middle+ и senior уровня 🫡

🔹Что будете делать?
Вы будете становиться частью разных команд в разных компаниях и разрабатывать проекты с нуля и поддерживать уже имеющиеся проекты.

Я знаком с CEO, мы в хороших отношениях и он по братски попросил закинуть новость в канал, чтобы ускорить набор людей на новый проект 🫡

🔻Я знаю что на меня подписано много классных и сильных специалистов, так что если вы вдруг ищете работу, отправляйте ваше CV @mary_yad с текстом:
Я классный middle+/senior разраб на unity. Пришел по рекомендации от Лёши, давайте попробуем поработать вместе 😊


Не разработчик, но работаешь с unity?
— Не беда, зайди на карьерную страницу, может там что-то подходящее найдешь 🫡

И надеюсь что у вас получится попасть в замечательную компанию 🥄

Я уже не работаю там, но буду рад ответить на любые вопросы в комментариях 👍

#рекомендации@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥25👍8
Интервью:
Клиентская архитектура корпораций


На unite 2025 я времени зря не терял и успел записать несколько интервью с разными интересными людьми.

В первом интервью я общался с Ярославом Шабанцом — клиентский архитектор в компании Playtika.
Именно под его руководством получилось "уговорить" Unity добавить в движок поддержку HTTP/2 для UnityWebRequest 😈

👇👇👇
Ссылка на видео
👆👆👆

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

Может показаться что мы заранее договорились о том, что и как мы будем отвечать, но еще задолго до интервью, на некоторые темы затронутые темы я писал посты:
🔸 СТРУКТУРА ПРОЕКТА
🔸 СТРУКТУРА СБОРОК
🔸 (А|а)рхитектура
🔸 ПРОЕКТИРОВАНИЕ: С ЧЕГО НАЧИНАТЬ

Приятного просмотра 🫡

Ты знаешь кому переслать этот пост 👍

#unite2025@UniArchitect
#интервью@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍13
Интервью:
Архитектура Open Source проектов


Второе интервью, которое я успел записать на Unite 2025.

На этот раз пообщался с Dzmitry Bazyleu — разработчик плагина UniState 200+⭐️ на GitHub.

Я постарался задавать вопросы, которые редко звучат в инфо пространстве, но которыми начинаешь задаваться когда ведешь разработку своего Open Source проекта:

🔸Как стартануть и не забросить open source проект?

🔸Какие архитектуреные решения нужно принять при старте open source проекта?

👇👇👇
Ссылка на видео
👆👆👆

У меня так же есть пара прикольных проектов в Open Source, где есть все элементы, которые мы обсудили с Димой:

🔸FastMigrations.Json.Net - плагин для миграции json файлов
🔸Unity Empty Project Template - шаблон пустого unity проекта

Ставь 👍 если тебе по кайфу такая движуха

#unite2025
#интервью@UniArchitect
👍34🔥10💯4💩1
CoreCLR в Unity - это круто🫡

Ты написал программу на C#, скомпилировал, получил .exe. Запускаешь — а Windows говорит "requires .NET Runtime". Почему?

Потому что C# компилируется не в машинный код, а в IL.
Windows не умеет его исполнять напрямую.
Нужен "движок исполнения" — runtime, который ты устанавливаешь отдельно (или он идёт bundled с приложением).

Runtime берёт IL и превращает в работающую программу.
Он определяет как каждый объект размещён в памяти, когда эта память освобождается, как вызываются виртуальные методы, как работают generics.

🔸Ключевые компоненты

▫️ Type System — хранит информацию о типах в памяти. Layout объекта: сначала Object Header (индекс SyncBlock для lock/hash), затем указатель на MethodTable.

Пример:
obj is IMyInterface. Runtime берёт MethodTable объекта (первое поле после header), смотрит в Interface Map — массив интерфейсов которые тип реализует.
Если интерфейс в списке — true. Для классов ещё проще: проход по цепочке Parent MethodTable.
Всё это O(1) или O(глубина наследования).

▫️ Virtual Machine (Execution Engine) — сердце runtime. Управляет потоками, загрузкой типов, виртуальными вызовами, координирует все подсистемы

▫️ JIT Compiler — компилирует IL в машинный код

▫️ Garbage Collector — управляет памятью, решает когда освобождать объекты

▫️ Interop — мост между managed и native кодом

🔸Почему это важно для Unity. Domain Reload.

Меняешь скрипт — Unity перезагружает весь managed домен. Выгружает ВСЕ сборки, пересоздаёт ВСЕ типы. На большом проекте это десятки секунд после каждого изменения.

CoreCLR предоставляет AssemblyLoadContext (ALC) — механизм изоляции сборок. Как это работает:

🔹Default ALC загружает framework и core assemblies — они живут всё время
🔹Custom ALC может загружать пользовательские сборки изолированно
🔹Collectible ALC позволяет выгружать сборки когда они больше не нужны

Т.е. вместо "выгрузить всё и загрузить заново" можно:
Cоздать новый ALC → загрузить изменённую сборку → переключить ссылки → выгрузить старый ALC. Framework, Unity assemblies, неизменённые скрипты остаются на месте.


🔻 Вот и 1 пункт почему переход на CoreCLR это круто - время Domain Reload может снизится в десятки или сотни раз, что == увеличению скорости итерации 😎

Дальше — как устроены Mono, IL2CPP и CoreCLR изнутри.

Ставь 👍 если тебе заходит такого рода контент!
Ты знаешь кому переслать эту статью 💪

#unite2025@UniArchitect
#проект_в_разработке@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍187🔥9💩21
Mono vs CoreCLR

Последние несколько лет я много писал серверного кода на dotnet, и меня постоянно радовала скорость итерации.
Делаешь изменение — почти моментально получаешь отклик. В Unity это всегда боль.

Я постоянно стараюсь работать так, чтобы как можно реже триггерить Domain Reload.
Эта штука на каждое, даже мелкое изменение отнимает десятки секунд.
Если взять обычный день и просто посчитать время на ожидание — легко набегут десятки минут.

🔸Почему так происходит?

Редактор Unity на всех платформах работает на Mono — старом кроссплатформенном runtime. В его основе лежит JIT-компиляция.

Когда вызывается твой метод первый раз, туда прописан вызов JIT-компилятора.
Он берёт IL-код метода, конвертирует в Mono IR (внутреннее представление Mono), оптимизирует, и только после этого генерирует инструкции для конкретного процессора.

Казалось бы, при чём тут мы? А при том, что Mono JIT — операция не бесплатная. И в редакторе она обходится очень дорого.

🔸Domain Reload

Его порядок работы примерно такой:

1️⃣ Находим все MonoBehaviour и вызываем OnDisable/OnDestroy
2⃣ Выгружаем все *.dll движка и наши
3⃣ Освобождаем GC Handles и выгружаем Domain
4⃣ Создаём новый Domain и загружаем все *.dll движка
5⃣ Загружаем все *.dll игрока
6⃣ Запускаем скрипты с [InitializeOnLoad]
7⃣ На пересозданных MonoBehaviour вызываем Awake/OnEnable

На моём проекте Magic Battle Arena (~100к строк кода, 149 сборок) эти 7 пунктов занимают 12 секунд.
Угадайте какая операция самая долгая?

Mono JIT — примерно 5.5 секунд в сумме.

Это происходит потому, что мы вынуждены полностью выгрузить ВСЕ *.dll (для которых методы уже скомпилированы) и перекомпилировать их заново.

🔸Почему это нельзя исправить в Mono

Проблема фундаментальная. В Mono нет механизма hot swap для сборок. Нельзя сказать "выгрузи только эту dll и загрузи новую версию".
Только полная перезагрузка домена.

CoreCLR решает это через AssemblyLoadContext, см. прошлый пост

🔸RyuJIT vs Mono JIT

Но даже если Unity не реализует hot reload, сам JIT-компилятор CoreCLR (RyuJIT) работает иначе.

Mono JIT — однопроходный. Скомпилировал метод один раз — живи с этим. Хочешь лучше? Используй AOT.

RyuJIT поддерживает Tiered Compilation:
🔹Tier 0: быстрая компиляция без оптимизаций (для быстрого старта)
🔹Tier 1: метод был вызван более 30 раз и более? — Оптимизируем его

Т.е. при Domain Reload методы сначала компилируются максимально быстро, а потом в фоне докомпилируются с оптимизациями.
Время ожидания сокращается, performance не страдает.

Но выиграем мы от смены JIT компилятора, я уверен не так много, как c перехода с Domain Reload на Code Reload.

🔻Мой прогноз:
Время Domain Reload снизится минимум на 75%.
В моём примере — с 12 секунд до 3. Останутся только вызовы Awake/Destroy и десериализация состояния сцен.

Проверим в 2025 2026 или 2027 году 🤣

Теперь ты знаешь что загадать на Новый Год 😊

Ставь 👍 если тебе заходит такого рода контент!
Ты знаешь кому переслать эту статью 💪

#unite2025@UniArchitect
#проект_в_разработке@UniArchitect
Please open Telegram to view this post
VIEW IN TELEGRAM
👍78🔥7💯2
ПРОЕКТИРОВАНИЕ: КОНТЕЙНЕРЫ

Многие хотят попробовать себя в роли архитекторов, но не очень понимают с чего начать.
Много раз видел как программисты, желая показать "архитектуру", отдавали схемы классов и связей между ними, думая что этого достаточно.

Проблема в том, что схема классов — это уровень кода. Самый последний уровень, который избыточен и не нужен.
Начинать проектирование с него — всё равно что строить дом, начиная с выбора дверных ручек.

В прошлой статье мы разобрали первый уровень модели C4 — System Context.
Он общий почти для всех игр на Unity, достаточно абстрактный и содержит мало конкретики.

Сегодня поговорим про второй уровень — контейнеры.

🔸Что такое контейнер

Контейнер в модели C4 (никак не связано с Docker!) — это приложение или хранилище данных. То, что должно быть запущено для работы всей программной системы.

Ключевой критерий: контейнер — это независимо деплоемая единица.

Примеры контейнеров:
▫️ Серверное приложение — http или любой другой сервер с логикой системы
▫️ Клиентское web-приложение — админка для управления данными пользователей
▫️ Мобильное приложение — бинарник, который пользователь скачивает на телефон
▫️ База данных — SQL или NoSQL решение для хранения данных игроков

Т.е. после того как у тебя готов общий уровень системы, ты определяешься какие элементы будут публиковаться и деплоиться независимо друг от друга.
Берёшь каждый элемент системы и разбиваешь его на отдельные деплоемые части.

🔸Пример: сервер для маленького проекта

Вот как бы я принимал решение о том, как сделать небольшой игровой сервер (< 100k скачиваний и 1k DAU).

Прикинем нагрузку. RPS на таких объёмах будет достаточно низкий:

1000 [игроков] / 24 [ч] / 60 [мин] / 60 [сек] ≈ 0.01 req/sec


Одного экземпляра http сервера на любой технологии будет более чем достаточно.
Значит всё серверное приложение — это 1 docker image, который можно опубликовать в Yandex/Google/Amazon Compute Cloud.

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

🔸Практические рекомендации

🔹 На крупных проектах может быть огромное количество элементов. Нет смысла упарываться в детализацию всех контейнеров всех элементов системы. Указывай только то, что нужно конкретному проектируемому элементу. Зависимости вне твоей зоны ответственности уточнять не нужно.

Пример из Hero Wars: для чата мы используем MQTT сервис, на топики которого подписывается клиент чтобы получать новые сообщения. Когда я проектировал чат, я не уточнял из чего состоит MQTT сервис и что он использует внутри — это избыточно и вне моей зоны ответственности.

🔹 На этом этапе полезно прописывать технологии, если они важны для проектируемого сервиса.

Для того же чата на серверной стороне для общения сервисов между собой используется Kafka.
Решение о том как организовано взаимодействие сервисов уже принято — указываем конкретную технологию, упрощаем схему и делаем её более информативной.

🔹 Unity-клиент на этом уровне детально не проектируется.

Любое Unity приложение — это монолит и всего 1 деплоемый unit.
Максимум что можно указать на схеме — платформы куда деплоимся. Но в большинстве случаев это избыточно.

🔻Проектирование можно и нужно начинать с двух простых шагов: сначала система и её ключевые элементы, затем уточнение каждого элемента деплоемыми unit'ами и технологиями.

Так ты получаешь не просто каркас, а полноценное верхнеуровневое понимание функционирования всего приложения.

Это вторая статья серии про проектирование. Дальше: компоненты и код.

Ставь 👍 если тебе заходит такого рода контент!
Ты знаешь кому переслать эту статью 💪

#проектирование@UniArchitect
👍39🔥21