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

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

@uniarchitect

Пишу о том, что нельзя нагуглить про архитектуру, разработку и пр.

Мой курс по архитектуре: https://course.uniarchitect.dev/y/9b8ec0c

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

По всем вопросам: @vangogih
Subscribers
5.24K
Photos
35
Videos
2
Links
99

Showing posts older than #45 · Back to latest

Older Posts 18 shown
Post #44 2.86K
SILVERFOX GAMES НАЧАЛО

Краткий карьерный путь

Осенью 22 мне на Linkedin постучался партнер и предложил сделать свою игру.
Кстати, добавляйтесь в друзья 👋

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

Я составил список команды и расходы на нее, партнер подготовил P&L. Решили сделать прототип под который будем поднимать намеченную сумму в 400.000$ на 1 год разработки.

Через пару месяцев был готов прототип. Под него партнер сделал питч. Начали рассылать по инвесторам.

Не хочу чтобы кто-то питал иллюзий насчет подъема pre-seed раунда под идею.
Такое в реальности делается только если есть огромный послужной список. 10+ лет над AAA в Ubisoft например.
В остальных случаях это FFF (Family, Friends, Fools). Наша история не исключение.

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

Соглашусь с мыслью из книги “Гении и аутсайдеры”, о том что большую часть успеха определяет контекст времени.
У нас это был Март 2022. Мягко говоря не самое простое время для фаундеров из России.

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

Какие выводы:
▫️ Поднять pre-seed можно только если у вас друг ангел-ивестор, родители при ресурсах, либо у вас огромное комьюнити, которое вы успешно монетизируете.
Либо вы успешный выходец популярной студии.
▫️ Если вам посчастливится поднять pre-seed. Не спешите тратить деньги, нанимать огромный штат и стартовать разработку.
Лучше маленькая мобильная, гибкая команда и четко выверенные шаги, которые при минимальных затратах дадут понять жизнеспособность идеи.
Чем со старта структура из 15-20 человек, которая менее мобильна, потребляет больше денег.
▫️Игры ОЧЕНЬ дорого, ОЧЕНЬ долго и ОЧЕНЬ сложно.
Success rate игровых проектов ~8%.
Как по мне, если вы хотите создать компанию, то начинать с игровой студии супер рисково.
Начните с чего попроще и подешевле: SaaS или точеное B2B решение.
▫️А еще, скорее всего вы не станете более желанным на рынке кадров только за счет того что у вас за спиной опыт создания своей компании.

#моя_история@UniArchitect
  • 👍 10
  • 🔥 4
  • 🤯 3
Post #43 2.64K
СТРУКТУРА СБОРОК

Сборки (Assembly definition, asmdef) — unity обертка над сборками в .NET.
По факту это json в котором прописана конфигурация .NET Assembly.

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

У себя на проектах я выделяю такие сборки:
🔹 Runtime — клиентский код
🔹 Editor — утилиты редактора
🔹 Tests.PlayMode — интеграционные тесты.
Т.е. тесты, для которых требуется unity scripts lifecycle
🔹 Tests.EditorMode — unit тесты

Для онлайн приложений так же выделяю:
🔹 Transport — cпецифичная для клиента связь с сервером. Реализация подключения, обмена данными, переключение состояний
🔹 Shared — общие с бэком модели данных, константы, конфиги и прочее.

Т.е. эти сборки является моделью домена и явно отделяют отображение unity (слой Presentation) от источника данных (слой Data Source)
Что-то на архитектурном, будет отдельный пост про это
Выделение этих частей позволяет mock'ать клиентскую часть и запускать клиент без unity т.е. должны стоять галки No Engine References

Из интересного:
▫️ В define constrains поддерживает отрицание. Т.е. можно выключить всю сборку для PROD define’ов
▫️MonoBehavior нельзя добавить как компонент на объект если в Platforms отмечен только Editor
Чтобы это обойти, поставьте галку на любую платформу, под которую 100% проект никогда не будет собран (Stadia например)
▫️ Для удобства редактирования и отслеживания изменений в git, уберите галку Use GUIDs
▫️ csc.rsp можно положить рядом с asmdef и прописать туда дополнительные параметры компиляции
Удобно когда нужно подключить большой список define’ов или отключить надоедливые warning’и
▫️Можно делать точеные оптимизации или патчи IL кода через Mono.Cecil или Harmony. Так раньше был сделан inject в VContainer
▫️Если сборка не изменилась, то перекомпилироваться она не будет. Таким образом, разбивая крупные сборки на более мелкие, можно значительно снизить время компиляции проекта. Из комментов, спасибо @Bogotoff.

А какие сборки вы выделяете в своих проектах?
👨‍💻 в комменты, я создал

#проект_с_нуля@UniArchitect
  • 👍 13
  • 🍌 1
Post #42 3.04K
DI

DI (Dependency Injection) — подход, который абстрагирует создание объекта, выделяя его на отдельный слой и отделяя от основного приложения.
Добавляет концепцию управления зоной использования (scope) и временем жизни объекта.

При том важно разделять:
🔹Composition Root (CR) — паттерн, подход при котором создание объектов системы происходит в одном месте.
Выделяет 3 (RRR) фазы управления жизненным циклом объектов:
- Register — создание зависимостей
- Resolve — решение графа зависимостей
- Release — удаление, освобождение объекта

🔹DI container (DIc 🍆) — как правило плагин, реализация-автоматизация CR.
Т.е. вместо ручного создания и решения графа зависимостей, он через рефлексию или кодогеном сам прокидывает зависимости в конструктор или поля.

🔹Service Locator (SL) — создает, хранит и отдает по требованию любое множество зависимостей
Может быть частью реализации CR, но тогда решать граф нужно самому.
В этом месте, при не понимании RRR, возникает куча проблем (кольцевые зависимости, классы боги) из-за чего SL называют антипаттерном.

Из этого следует:
▫️Реализовать DI можно без использования DIc
▫️DIc (Zenject, Vcontainer и др.) сильно расширяют жизненный цикл любого класса
▫️С DIс мы делегируем обязанность по созданию и управлению жизненным циклом объекта!
▫️Легковестной реализацией DI может быть SL (статический класс со словарем)

При использовании DIc или SL важно навсегда запомнить:
1. Никакой логики в конструкторе. Только агрегация и композиция
2. Вся логика инициализации, как отдельная стадия создания объекта, выделяется в отдельный метод

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

Картинка из книги Dependency Injection Principles, Practices, and Patterns by Steven van Deursen and Mark Seemann

#проект_в_разработке@UniArchitect
#аббревиатуры@UniArchitect
  • 👍 31
  • 🤔 1
Post #41 2.74K
FTUE

Для программиста — жизнь это while(true)
Для CG художника — жизнь это lerp(a,b,t)
Для аналитика — жизнь это funnel

В прошлый раз я писал про Retention (R).
Но от чего зависит R и можно ли его как-то предсказать?
— Можно если знать конверсию FTUE воронки.

Воронка (funnel) — последовательность шагов, по которым проходит группа пользователей.
Пример:
— Установка
— Согласие с GDPR (General Data Protection Regulation)
— Загрузка ассетов из CDN (Content Devilery Network)
— Шаги тутора
— Сыгранные N игр в core части

Из прохождения всех шагов складывается первое впечатление пользователя от игры — FTUE.
FTUE (First time user experience) — воронка, которую проходит пользователь до возврата на 1 день.

Замерами мы понимаем эффективность шагов. И если она не достаточная, то мы улучшаем его, делая первый опыт игрока более приятным, тем самым влияя на R1.

Из интересного:
▫️ Для R1 ~30-35% конверсия FTUE должна быть ~60-70%
▫️ Аномальное изменение % отвала между версиями == техническая проблема (софт/хард лок, ANR)
▫️ Эффективность изменений в обновлении == дельта отвала между текущей и прошлой версией
▫️ 500 пользователей — минимально достаточное кол-во, чтобы считать данные репрезентативными

⚠️ Эксклюзив: фрагмент документа с одного из проектов, над которым я работал.

#проект_liveOps@UniArchitect
#метрики@UniArchitect
  • 👍 3
  • 🔥 2
Post #39 3.35K
НАВИГАЦИЯ

Об авторе блога

Open source:
— Unity Empty Project Template 80+⭐️
— Fast Migrations Json .NET 40+⭐️

#проект_с_нуля@UniArchitect — все что нужно знать, когда создаете новый проект

#проект_в_разработке@UniArchitect — все с чем приходится сталкиваться во время разработки

#проект_релиз@UniArchitect — нюансы, процессы, проблемы публикации мобильных проектов

#проект_liveOps@UniArchitect — поддержка, оперирование приложениями, которые уже опубликованы

#аббревиатуры@UniArchitect — высказываюсь на тему популярных аббревиатур

#моя_история@UniArchitect — истории моего карьерного и не только пути

#метрики@UniArchitect — аналитические метрики проекта, которые полезно знать

#будни@UniArchitect — реальные проблемы, с которыми я сталкиваюсь и сразу пишу об этом

#software_engineering@UniArchitect — цикл статей на тему инженерной разработки ПО.
Основа для понимания архитектуры ПО

#курс@UniArchitect — статьи, где я делюсь прогрессом по курсу, который я проработал и создал

Мероприятия:
#DevGAMM_Lisbon_23@UniArchitect
#unite2025@UniArchitect

@UniArchitect
  • 👍 6
Post #36 3.07K
ВЕРСИОНИРОВАНИЕ Ч.2. МИГРАЦИЯ

Ч.1. СЕМАНТИКА

В первой части я говорил что поддерживать обратную совместимость для игр нет смысла, потому что API нет.
Исключение — профиль игрока. Его обратную совместимость мы должны обеспечивать всегда.

Страшный сон для игрока — потеря прогресса.
Страшный сон любого проекта — ошибки с локальным профилем игрока.
Если профиль не синхронизирован с сервером, а игрок потратил деньги, то можно ловить кучу 1 ⭐️ в сторах, возвращать всем деньги и смело ставить свечку за упокой проекта 🕯

Чтобы сон не стал явью нужно позаботиться о миграциях профиля игрока.
Миграция — преобразование данных формата одной версии в формат другой.

Пример:
- Профиль игрока версии 1.0.0 — { “coins”: 100 }
- Переименовали coins в soft, версия 1.1.0 — { "soft":100 }
- Объединили поля с валютами в объект, версия 1.2.0 —
{ "bank": { "soft":100, "hard":10 } }

Если не будет миграции игрок получит ошибку десериализации при запуске игры после обновления. Потому что json schema между версиями разная.

Решение:
Json файл нужно версионировать. При изменении схемы (поломке обратной совместимости), писать миграции.

Задача сводится к тому чтобы написать свой JsonConverter, который будет брать все объекты миграции с версии k до n и вызывать их методы.
Где k - версия json у пользователя, n - версия json в проекте

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

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

Смотрю на плагин и слышу как это интерпрайзное говно кричит о том чтобы его переписали и упростили.

Давайте 15 👍 этому посту и я за пару недель
👨‍💻 свою версию, которую вы сможете использовать в своем проекте.

Обещание выполнено!
https://github.com/vangogih/FastMigrations.Json.Net

#проект_релиз@UniArchitect
  • 👍 33
Post #35 2.28K
СТРУКТУРА ВЕТОК ПРОЕКТА

У структуры веток всего 1 требование — деление процесса разработки на понятные стадии.

Из опыта создания нескольких проектов с нуля я выделил такую структуру веток:

🔹 develop — разработка.
- В этой ветке происходит контролируемый разработчиками хаос
- Код в ветке может работать, а может и нет
- Окружения разворачивается локально
- Настройки проекта могут быть какие угодно в зависимости от потребностей разработчиков

🔹 art — стабильная версия develop.
- Нужна геймдизайнерам, QA, аналитикам и т.п. для проверки, тестирования текущего состояния приложения
- Cвое серверное окружение

🔹 stable — feature freeze. Выделяет конкретный список, набор фичей, которые получат пользователи в этом обновлении.
- Сюда мержится develop когда все фичи версии сделаны
- Включена вся отладка
- Включены читы
- Фейковый магазин
- Cвое серверное окружение

🔹 rc — Release Candidate. Это пред-релизная версия.
- В данную ветку мержится stable
- Сюда могут быть залиты только hotfix’ы
- Версия максимально приближена к проду
- Отключена вся отладка
- Конфигурация на максимальную производительность
- Реальный магазин
- База данных синхронизирована с продом

🔹 main/master — тот самый prod, который принято ронять 😬
- Сюда мержится rc
- Состояние из этой ветки всегда соответствует состоянию приложения у пользователей на девайсах.
- В нее может напрямую пушить только лид, либо ответственный за релиз.

Кол-во веток и окружение нужно варьировать в зависимости от потребностей проекта.

#проект_в_разработке@UniArchitect
  • 👍 7
Post #34 2.03K
ПЕРЕКЛЮЧЕНИЕ СЦЕН — Additive.

СЦЕНЫ

Нюансы:
— Загрузка и выгрузка асинхронная, требует написания доп. кода
— Нужно ручками в новой сцене дергать SceneManager.SetActiveScene
Только после этого делать Instantiate объектов.
— Сторонние плагины все равно создают DontDestroyOnLoad объекты

Преимущества:
— Можно отказаться от DontDestroyOnLoad объектов и использовать Bootstrap сцену для хранения глобального контекста.
— Захотели перезапустить игру полностью? Загрузили заново Bootstrap и весь контекст дропнулся без лишних телодвижений
— Очистка памяти и уменьшение используемой RAM без Empty сцен

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

#проект_с_нуля@UniArchitect
  • 👍 6
  • 🔥 1
Post #31 2.19K
С ПОЛЕЙ РАЗРАБОТКИ:
ОПТИМИЗАЦИИ ЗАГРУЗКИ

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

Вводные:
1️⃣ Карта с 5 уровнями. Группа из 5 уровней называется остров.
1ый остров - тутор
ГК - глобальная карта на которой находятся все острова
2️⃣ Игрок прошел последнюю карту 1го острова (т.е. тутор), нажимает кнопку открытия ГК (это scrollRect горизонтальный с 10+ элементами) и получает ANR.
3️⃣ В логах перекати поле. Нет ничего. Ни одной ошибки ни одного warning'a.

ANR коротко — главный поток висит >5 секунд?
— Android ядро грохает приложение.

Причина:
— Instantiate большого кол-ва объектов в одном кадре
— Canvas.ForceUpdateCanvases(); занимает >1000ms на компе. На девайсе замерить не удалось, угадайте почему 🤷‍♂️

Решение:
— Если в одном кадре много Instantiate - делаем из метода корутину и проставляем delay (или return null) после каждого выполнения тяжелой логики
— Перед добавлением элементов включаем сам объект в иерархии, на котором будут создаваться объекты

Это позволит не в один кадр обновить все добавленные на канвас элементы (а это куча примерно в 1000 объектов), а в несколько.

p.s. обожаю фиксы в одну строку (см. последний скрин, это весь фикс)

Насколько вообще заходит такой формат, черканите коммент 😊

#будни@UniArchitect
  • 👍 11
  • 🆒 8
  • 🤷‍♂ 1
Post #30 1.75K
Post #29 1.84K
(А|а)рхитектура

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

Архитектурные подходы (паттерны) в разработке ПО универсальны. Их можно применить к любому языку и проекту. Код, следующий этим принципам, будет ➕➖ одинаков с точки зрения масштабируемости и сложности.

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

И при проектировании нужно вырабатывать эти решения (правила, подходы, гайдлайны) не только для кода, но и для всего с чем проект связан:
— Именование файлов и папок, структура хранения ассетов, структура сборок
— Утилиты для разработки, тестирование, работа с системой контроля версии
— Билд проекта и его деплой, работа со сторами и выливка хотфиксов
— Мониторинг метрик, ошибок и реагирование на них

#аббревиатуры@UniArchitect
  • 🔥 2
  • ⚡ 1
Post #28 1.9K
СЦЕНЫ

Первая проблема, которую я сразу решаю на новом проекте — 4 сцены для управления состоянием проекта.

0.Bootstrap — точка входа и контекст проекта (аналитика, SDK сторов, платежка, конфиги, связь с сервером).

1.Loading — загрузка, авторизация, GDPR, проверка обновлений и прочее что нужно для старта игры.

2.Meta — в основном UI в котором вы тратите накопленные ресурсы на прогресс по игре

3.Core — основная реиграбельная часть

4.Empty — костыль сцена для 100% выгрузки всех ресурсов предыдущей сцены.

Из любой сцены мы можем перейти в любую. Исключение Bootstrap. В нее входим только при запуске игры. И из нее загружаем только Loading.

#проект_с_нуля@UniArchitect
  • 👍 11
Post #26 1.6K
Retention (R)
Первая и базовая метрика, которой измеряется успешность проекта.

Всего 2 типа:
Classic retention — % пользователей, которые открыли игру на следующий день*
Rolling retention — % пользователей, которые открыли игру на следующий день* или позже

Минусы второго — может измениться в любой момент. Даже если пользователь зайдет в игру в следующий раз на 90 день, он попадет в Rolling R1.

Следующий день* — есть 2 типа интервала от которого можно замерять R:
1. 24h — пользователь будет учтен, если откроет приложение в период 24-48 часов после установки.
2. Calendar — пользователь будет учтен, если откроет приложение на следующий календарный день.

Минус второго — пользователь, который скачал игру в 11:50 вечера и открывший ее в 12:05 следующего дня будет учтен.

Из интересного:
▫️ Изменение R1 — динамика развития проекта
▫️ Rolling R на практике используется редко, чаще упоминается на публике или на слайдах в отчетах
▫️ 24h R можно использовать для быстрого определения эффективности компании. Это работает т.к. мы можем в данном случае измерить возврат 0-го дня.
▫️ Calendar Classic R чаще всего просили показать инвесторы. Многие кто слышал цифры ниже бэнчмарков сразу разворачивались
▫️ Если на старте R1 ниже 20%, а FTUE уже отлажен, то потребуются координальные изменения в core части игры, чтобы проект выжил
▫️ Если на старте R1 около 15 и ниже, то проект дешевле убить чем вытягивать
▫️ Если R1 > 35% это успех

#проект_liveOps@UniArchitect
#метрики@UniArchitect
  • 👍 6
  • 🔥 3
Post #23 1.51K
ВЕРСИОНИРОВАНИЕ Ч.1 СЕМАНТИКА

На многих проектах, на которых удалось поработать, я замечал, что версионирование ведется по принципу увеличиваем последнюю цифру. Если последняя цифра больше условных 10, то мы изменяем предпоследнюю цифру на единицу, а последнюю цифру обнуляем. И так далее.
То есть это работает как какой-то счетчик, разделенный тремя точками.
Практического смысла и какой-то идеи я никогда не наблюдал.

Мы все знаем про семантическое версионирование, но не знаем как его применять для игр. А дело в том, что семантическое версионирование для игр и не работает. Потому что нет как такового публичного API, для которого будут работать его правила.

Мы не можем обновить игру так же, как мы можем обновить Nuget зависимость. Нам не нужно беспокоится об обратной совместимости. Я к тому, что использовать схему major.minor.patch нас никто не заставляет.

Ну как никто, есть один профессиональный объюзер в мире разработки — Apple. Оо, сколько у меня вопросов к этим ребятам. Они заставляют придерживаться схемы major.minor.patch. И остается лишь под это адаптироваться.

В итоге требование к изменению версии всего одно — текущая версия должна быть выше предыдущей. А схема — major.minor.patch.

И с опытом я сформировал такие правила изменения версии:
— major - когда игра не опубликована - 0, после публикации 1. Дальше +1 когда minor достигнет 99 или когда будет очень крупное обновление.
— minor - меняем при каждом релизе
— patch - только для хотфиксов

Пример:
— В develop версия 1.0.0, stable, rc, master версия 0.2.0
— При критической ошибке в 0.2.0 в rc делаем хотфикс и версию меняем на 0.2.1.
— Когда проект будет опубликован в сторах, его версия в master будет 1.0.0, а develop 1.1.0.
— Если в 1.0.0 будет баг, то в stable, rc, master будет вылит фикс, а версия изменится на 1.0.1.

А bundle version code можно формировать по формуле: major * 10000 + minor * 100 + patch. Но с оговоркой что вы готовы менять версию каждый раз при косячной заливке в стор.

Я же отказался от этой формулы и просто перед каждой заливкой в стор ручками увеличиваю bundle version code на 1. И он с версией никак не связан.

При том в вопросе версионирования остается еще один нераскрытый момент — миграция данных между релизами. Об этом мы поговорим в следующем посте данного цикла 😊

#проект_релиз@UniArchitect
  • 👍 4
  • 🔥 3
Post #22 1.42K
ПЕРЕЕЗД В ИСПАНИЮ 🇪🇸

Я давно мечтал переехать в одну из стран Европы. После долгих изучений и постоянных переездов из страны в страну, стало понятно что нужно где-то обосноваться. Наш с женой выбор пал на Испанию.

1️⃣ Климат
Жене и мне надоела серая московская погода. Либо дикая аномальная жара, либо аномальный холод или отсутствие снега.
Так же, как человек из Сибири, привыкший к холодам и хорошей студеной зиме со снегом, то что происходит в Москве не поворачивается язык назвать это зимой. А я люблю зиму 😞
Осень/весна занимают половину года, а иногда и все 3/4. Слякоть, дожди, серость, все это очень сильно бьет по моральной и продуктивной составляющей.

2️⃣ Менталитет и отношение
Обеденные сиесты в 2 часа, когда можно сгонять домой, покушать, поспать и вернуться домой.
Женщин, детей и даже животных здесь уважают больше чем мужчин. Не поймите не правильно, просто когда в Москве жену страшно посадить одну в такси это не ок.

3️⃣ ВНЖ выдают с российским ИП
Я уже 3 года работаю удаленно как ИП. Испания в начале этого года открыла nomad ВНЖ программу по которой можно получить вид на жительство на 3 года. Процедура пока очень простая с самым низким порогом входа. + принимаю контракты из РФ и ИП в РФ тут котируется.
Дайте знать если интересно, могу сделать отдельный пост, где опишу весь этот длинный путь.

И сейчас как раз занимаюсь подготовкой и подачей документов на nomad ВНЖ.

В данном цикле хотелось бы больше рассказывать о себе, напишите про что интересно почитать:
— С чего все начиналось (школа, универ, самообучение)
— Последний опыт (своя игровая студия, переезды, события последних 2ух лет)

#моя_история@UniArchitect
  • 🔥 10
Post #20 1.79K
СТРУКТУРА ПРОЕКТА

Папка проекта

Перед тем как написать первую строчку кода, нужно решить очень важную проблему — быстрое захламление иерархии проекта. Чтобы последующие N-лет работать с ней без головной боли.

Обычно происходит как: создается проект, в этой же папке создается git репозиторий — profit.

Например:
У вас плание backend с общей shared частью (это общий код для бэка и клиента, например модели). И вам нужно где-то хранить скрипты для копирования shared части.
Или бэкенд лежит в одном репозитории с клиентом.
Или CI/CD пайплайн потребует запуска кастомных скриптов.
Или есть внешние конфиги, которые вы хотите хранить вне папки Assets, чтобы они не попали в билд (например конфигурации сборки билда).
+ unity генерирует кучу папок, которые не попадают в репозиторий, но есть локально (Library, Debug, Temp, obj и прочие).
+ файлы, которые генерирует Rider и VS.

Поздравляю! Ваша когнитивная сложность выросла в 5 раз, а иерархия превратилась ПОМОЙКУ 🤥

КАК ЭТОГО ИЗБЕЖАТЬ?

У себя на проектах я делаю такую иерархию:
+-- %project_name%
| +-- .git
| +-- %project_name%.Build
| +-- %project_name%.ExternalConfigs
| +-- %project_name%.ThirdParty
| +-- %project_name%.Keystore
| +-- %project_name%.Backend
| +-- %project_name%.Kubernetes
| +-- %project_name%.Unity
| | + -- Assets
| | | +-- _Project

Плюсы:
— Unity проект отображается в Unity Hub адекватно
— Внешние и внутренние файлы разделены
— Декларативность == низкая когнитивная сложность

Минусов нет 😎

Папка _Project

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

Со временем когнитивная сложность растет и поиск нужной папки отнимает все больше и больше времени.

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

Внутри _Project делаю такую иерархию:
+-- _Project
| +-- Art
| +-- Develop
| +-- Plugins
| +-- Resources
| +-- Scenes
| +-- прочие папки

Плюсы:
— Быстрая адаптация новых людей
— Легкая масштабируемость
— Поскольку наши файлы и файлы импортируемых ассетов лежат отдельно, обновление последних происходит без головняка и без риска задеть наши файлы

Минусы:
— Глубокая иерархия - увеличивает когнитивную нагрузку
— Требуется порядок и правила создания новых папок - чтобы со временем не стало помойки
— Некоторые папки типа StreamingAssets нельзя скопировать к себе в _Project

В следующем посте цикла "проект_с_нуля" — структура сборок

#проект_с_нуля@UniArchitect
  • 🔥 7
  • 👍 3
Post #19 1.75K
SOLID

Медийный продукт Роберта Мартина (ака Дядя Боб). Сколько книг он написал и конференций провёл, где рассказывал 5 заветных принципов “как писать код и какими принципами руководствоваться”. Я прочитал не одну его книгу и могу сказать - он хорошо продвигает свою идеологию, проникает в неокрепшие умы и плотно там закрепляется.

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

У меня первый надлом в его принципах произошел из-за постоянных переработок и непопадания в сроки. Зачем писать кучу ненужного кода…

Второй - когда я устроился на второй проект. Там от его принципов не просто отказались, а даже не слышали. И знаете что? Проект в сотни раз проще масштабирутся, дебажить его проще, а самое главное логика лежит на поверхности. Никакой сотни классов и название FooAbstractFactorySingletoneFacade3000, которое можно использовать как стоп-слово 🤔

Тогда я понял, что слепо веровать и следовать - максимально непродуктивно.

Только 2 принципа оказались хоть как-то применимы на практике и хоть чуточку полезными:
DIP — когда вы можете разорвать кольцевую зависимость и развернуть связи в обратном направлении.
ISP — бывает удобно выделить интерфейс или несколько, и написать всего 1 обработчик.

Все. Остальное расплывчато сформулировано (OCP), устарело (LSP) и почти не применимо на практике (SRP).

Дядя Боб — инфлюенсер-зумер. Этакий инфоцыган, до того как это стало мейнстримом. Ведь до эпохи соц.сетей и блогов единственный способ стать известным и заработать на этом — книги.

Что мы имеем в сухом остатке?
— Популярную идеологию, которая распространена по всему СНГ и ближней Европе (за другие локации не скажу).
— Кучу новичков и опытных программистов, которые ей следуют и заставляют следовать других.
— Тысячи загубленных проектов, которые проще написать с нуля, чем поддерживать дальше.

Зафиналить хочу так — есть реальная проблема! Обучающего контента, уровня реальных проектов, очень мало, даже по архитектуре. Я решил это исправить — создал этот канал.

В следующем посте цикла "аббревиатуры" — DI

#аббревиатуры@UniArchitect
  • 👍 9
  • ⚡ 6
  • 🤔 3
  • 😁 1
Post #6 1.72K
Всем привет!
Меня зовут Алексей и я Lead разработчик. А последний год CTO Silverfox.Games.

Я самоучка. Всё, что связано с разработкой игр, я изучал самостоятельно. Все мои знания - личный опыт.
Работал над 5 мобильными проектами в разных жанрах (mid-core, simulator, merge-3). А также делал несколько проектов в дополненной реальности.

Какие-то стали успешными, какие-то не очень. Но насколько успех продукта зависит от разработчика?

Проекты:
Magic Battle Arena (Android, IOS)
Combat Quest (Android, IOS)
Pool City (Android)
Overcrowded: Tycoon компания Zeptolab
WSOP Poker (50M+ скачиваний)
Текущий 👉 Hero Wars Alliance (100M+ скачиваний)

О чём я здесь пишу:
- об архитектуре игровых проектов на базе unity
- о создании проектов с нуля
- о своём пути разработчика игр

Я завсегдатый архитектурного чатика. Отвечая там на вопросы, я понял что тема архитектуры очень плохо освещена. А тупорылые best practices от unity часто не имеют ничего общего с реальными проектами.

Так же поделюсь своим отношением к паттернам и модным аббревиатурам. Обсудим, как это можно использовать на реальных проектах.
  • 👍 10
  • 🤯 2
  • ⚡ 1
  • 🔥 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →