Unity-разработчик: техническое портфолио без демосцены
Выберите систему, которая меняется под нагрузкой
Красивая сцена с готовыми assets показывает вкус и умение собрать окружение, но мало говорит о работе Unity-разработчика. Для технического портфолио лучше законченная система: боевой цикл с несколькими типами атак, inventory с сохранением, AI perception, процедурная генерация уровня, runtime customization, network prediction или tool для контент-команды. У системы должны быть состояние, ограничения, события и хотя бы одно изменение требований.
Опишите игрока и платформу. Mobile puzzle, VR training и PC action предъявляют разные требования к input, памяти, частоте кадров и сборке. Зафиксируйте target hardware, минимальный FPS, число сущностей, размер сцены и время загрузки. Тогда решение можно оценивать. Object pooling без измеренных allocations выглядит следованием моде; pooling после spike из-за сотни projectile одновременно становится понятным engineering trade-off.
Сократите визуальный scope. Используйте собственные простые primitives или лицензированные assets с credits, чтобы не тратить месяцы на art. Главное — читаемость поведения. Debug overlay, gizmos и inspector показывают внутреннее состояние лучше cinematic trailer. Запишите короткое видео для первого знакомства, но приложите repository, playable build, architecture note и профильные captures. Если часть кода закрыта NDA, сделайте отдельный минимальный reproduction того же решения.
Подберите проект под поток работодателей. Добавьте таблицу provenance: какие assets созданы вами, какие взяты из Asset Store, что изменено, по какой лицензии разрешена публикация. Для сетевой или backend-части так же отделите собственный код от готового SDK. Reviewer быстрее доверяет простому окружению с ясными credits, чем эффектной сцене с неясным авторством. Эта таблица также показывает, умеете ли вы готовить коммерческую поставку без лицензионного сюрприза. Проверьте проект на чистой машине или в CI cache miss. Скрытые packages в локальном disk cache, незакоммиченный Input Actions asset и абсолютный путь к streaming data часто обнаруживаются только там. Запишите точную последовательность clone, restore, test, build и запуск player. Вакансии Unity-разработчиков различаются между games, simulation, mobile и AR/VR; первый экран портфолио должен сразу назвать платформу, вашу роль, Unity version, ключевую систему и ограничения. Не заставляйте reviewer угадывать, что в сцене написано вами.
Покажите архитектуру через поток состояния
Начните с diagram зависимостей и одного runtime-сценария. Где живёт state, кто создаёт сущности, как input превращается в command, как gameplay сообщает UI, где сохраняется прогресс? Не нужно строить универсальный framework. Покажите границы, которые помогают изменению. ScriptableObject подходит для authoring конфигурации, но mutable runtime state в общем asset может протечь между play sessions или сущностями. MonoBehaviour удобен на scene boundary, но domain rules легче тестировать в обычных C# объектах.
| Область | Подходящая граница | Риск | Проверка |
|---|---|---|---|
| Конфигурация | immutable ScriptableObject | случайный runtime write | inspector test |
| Gameplay state | C# model/component | скрытая связь со сценой | unit test |
| Presentation | MonoBehaviour/view | логика в Update | play mode test |
| Save | versioned DTO | несовместимый слот | migration fixture |
| Events | typed channel/interface | утечка подписки | lifecycle test |
Объясните, где вы приняли coupling сознательно. Небольшой проект не выигрывает от пяти слоёв абстракции. Прямой reference на обязательный scene service может быть яснее service locator, если dependency видна и проверяется. С другой стороны, поиск объектов каждый кадр и глобальные singleton с неявным порядком initialization создают хрупкость. Покажите trade-off, а не число паттернов.
Событийная система требует ownership. Кто подписывается, когда отписывается, что происходит после scene unload, допускается ли replay? Static event способен удержать уничтоженный объект. В портфолио добавьте regression: несколько загрузок сцены не увеличивают число callbacks. Для async используйте cancellation, связанный с lifecycle объекта, и не продолжайте обновлять view после уничтожения.
Архитектура видна не по диаграмме классов, а по стоимости второго типа оружия, нового save field или смены input source.
Профилируйте на target device
Unity Editor удобен для поиска, но его цифры не равны player build. Снимайте CPU, GPU, memory и loading на целевом устройстве в development build, а затем подтверждайте release. Определите budget кадра: при 60 FPS около 16,7 мс делят gameplay, rendering, physics и другие системы. Средний FPS скрывает hitches, поэтому смотрите frame time distribution, worst frames и конкретные markers.
Профилируйте сначала, оптимизируйте после evidence. Deep Profile сильно искажает overhead; используйте его точечно. Добавьте свои ProfilerMarker вокруг систем, чтобы увидеть участок. GC.Alloc column помогает найти allocations в Update, но нулевые allocations не гарантируют скорость. LINQ в редком меню может быть приемлем, а сложный cache в горячем цикле — оправданным. Измеряйте эффект изменения тем же capture.
Для GPU отделите CPU-bound от GPU-bound. Frame Debugger показывает draw calls и batching, Rendering Debugger — pipeline features, device tools — время GPU. Уменьшение полигонов не поможет, если кадр ждёт скрипт; переписывание AI не исправит fill rate от прозрачных overdraw-слоёв. На mobile проверьте thermal throttling и длительную сессию: быстрые первые две минуты могут смениться падением частоты.
Контур связывает изменяемую систему, frame budget, content tools и проверяемый player build.
Подготовьте сборку и данные как production
Playable build должен запускаться без редактора и скрытых локальных файлов. Зафиксируйте Unity editor version, package lock, render pipeline, input system и build scenes. Секреты сервисов не храните в repository или Resources. Environment-specific endpoints передавайте через безопасный config процесса сборки. Добавьте CI-команду batchmode, которая компилирует scripts, запускает допустимый набор tests и собирает target.
Версионируйте save. DTO не должен быть прямой сериализацией всего runtime graph. Храните необходимые поля, schema version и миграции. Сделайте fixtures старого save и тест обновления. Обрабатывайте повреждённый файл без потери всех слотов: backup, validation и понятное сообщение. Для cloud save нужны conflict policy и idempotency, иначе два устройства перезапишут прогресс в случайном порядке.
Asset pipeline тоже показывает инженерность. Настройте import presets для textures и audio по платформе, Addressables groups по сценарию загрузки, проверку missing references и budget размера. Не кладите каждый мелкий asset в отдельный remote bundle без оценки запросов. Покажите dependency report и решение, почему часть контента встроена, а часть доставляется позже. Лицензии сторонних assets перечислите в credits.
Сделайте developer menu: выбор уровня, выдача ресурсов, замедление времени, отображение navmesh, hitboxes и AI state. Debug tools ускоряют QA и content iteration, но не должны попадать в публичную release-конфигурацию без защиты. Логи используйте структурно и ограниченно; тысяча сообщений в Update меняет производительность и прячет реальную ошибку.
Раскройте gameplay и инструменты одной историей
Возьмите изменение требования. Например, атака раньше наносила мгновенный damage, затем появились shields, damage over time и replay. Покажите старую границу, конфликт и новую модель: immutable damage event проходит modifiers, создаёт result, presentation воспроизводит feedback, analytics получает safe payload. Не обязательно выбирать именно этот паттерн. Важна последовательность, где новая задача выявила цену прежнего решения.
Добавьте editor tool для контента: custom inspector, validation window, graph, level brush или batch fixer. Опишите пользователя инструмента и ошибку, которую он предотвращает. Undo, multi-object edit, dirty state, prefab overrides и play mode — реальные края editor scripting. Инструмент, работающий только на вашей сцене, не доказывает handoff. Дайте дизайнеру задачу и зафиксируйте, сколько действий или ошибок изменилось.
Тестируйте deterministic core отдельно от engine integration. Damage formula, inventory rules и save migration подходят для edit mode unit tests. Scene wiring, physics contact, animation event и prefab lifecycle требуют play mode. Не пытайтесь проверять визуальное качество только asserts, но закрепите критические инварианты: событие не дублируется, destroyed target не получает callback, загрузка восстанавливает state, projectile возвращается в pool.
README проекта должен вести reviewer коротким маршрутом: двухминутное видео, build, управление, архитектурная схема, profiler before/after, известные ограничения и код двух ключевых модулей. Не публикуйте огромный Library или чужие binary assets без необходимости. Ориентиры оплаты доступны на странице зарплат Unity-разработчиков. Техническое портфолио убеждает, когда видно, как система переживает новый контент, слабое устройство и повторную сборку.