Оптимизация миров, построенных игроками: стратегия рендеринга SEED в Unity

  • PublicPublic
  • 06 Nov, 2026
Оптимизация миров, построенных игроками: стратегия рендеринга SEED в Unity

SEED - это персистентная MMO-песочница от Klang Games, разработанная на Unity. Действие разворачивается на далёкой планете, где игроки управляют автономными персонажами - ростками. В игре есть экономика, управляемая игроками, строительство общества и непрерывное расширение мира, которое продолжается даже после выхода игроков из игры. Каждая новая постройка, дерево или персонаж, добавленные игроками, увеличивают нагрузку на рендеринг в клиенте Unity, который должен обрабатывать это динамическое состояние на широком спектре железа - от мощных ПК до смартфонов. Симуляция работает на выделенных серверах, а клиент отвечает за рендеринг стримингового состояния и передачу действий игрока, таких как клики и движение камеры.

Арт-стиль SEED намеренно стилизован и низкополигонален: большинство данных о поверхностях хранится непосредственно в геометрии, а не в текстурах. Такой подход снижает затраты на шейдинг и использование пропускной способности памяти, что критически важно для производительности на мобильных устройствах. Здания строятся из маленьких кирпичных модулей на сетке с шагом один метр. Каждый воксель, размещённый игроком, разворачивается примерно в 15 модулей, при этом интерьеры генерируются только при просмотре. Крупнейшее общество на оживлённом острове насчитывает 172 здания, около 12 500 вокселей и 190 000 модулей. Они рендерятся с помощью BatchRendererGroup, где задачи выполняются в C# Job System и компилируются компилятором Burst, что обеспечивает эффективность даже при большом количестве объектов.

Klang Games использует Universal Render Pipeline (URP) и строго следует стандартным решениям Unity, чтобы гарантировать совместимость с будущими обновлениями. Игра сейчас работает на Unity 6.3, и команда обновляет движок примерно раз или два в год, чтобы получить доступ к новым функциям рендеринга. Кастомные эффекты реализуются через собственные renderer features, а не путём замены URP, что позволяет сохранить базовые механизмы, такие как SRP batching и GPU Resident Drawer. Для природных объектов используется Shader Graph со стандартным шейдером Lit, а для персонажей - Unlit-шейдеры с кастомным проходом освещения. Эта стратегия гарантирует, что создание собственных шейдерных графов не ломает базовые механизмы производительности, создавая стабильную основу для мира, где сложность рендеринга определяют игроки.

Взаимодействие с плотной средой, созданной игроками, требует точных методов выбора объектов. При приближении игра использует пиксельно-точный выбор: объекты рисуются в off-screen render target с уникальными ID, что позволяет клиенту точно определить объект под курсором. На мобильных устройствах, где ввод через касания менее точен, система проверяет соседние пиксели и показывает список выбора, если обнаружено несколько объектов. При отдалении система переключается на физический raycast, используя Unity Physics для инициализации и запроса огромного количества коллайдеров для деревьев, объектов и кирпичей зданий. Постоянно работающая задача определяет, находятся ли объекты внутри зданий, чтобы управлять слоями рендеринга и освещением, что позволяет, например, отключать GameObjects или настраивать видимость в зависимости от местоположения игрока внутри структуры.

Оптимизация производительности сильно опирается на реалистичные данные из снимков живых серверов, которые восстанавливаются локально для тестирования крупных обществ. Этот подход показал, что на ПК игра часто упирается в CPU из-за отправки draw calls, несмотря на использование GPU Resident Drawer. Проблема была связана с анимированным перекрёстным затуханием LOD, которое мешало инстансингу объектов. Отключив анимационную часть и используя ручные переходы, команда вернула инстансинг, что значительно снизило нагрузку на CPU. На мобильных устройствах главным ограничением является память, а не CPU. С помощью Memory Profiler команда выявила проблемы, такие как дублирование текстур и слишком большие коллекции C#. Чтобы решить вопрос с использованием памяти для геометрии, они заменили классические LOD Groups на Mesh LOD в Unity 6.2. Эта функция хранит все уровни детализации в одной меш-модели, что уменьшает потребление памяти и упрощает управление ассетами для мобильных платформ.