Unity 6.3
0 онлайн 86 гостей 3 в системе
Вход
Советы по повышению продуктивности в Unity 6 Глава 6 из 8 Оригинал, стр. 75

Рабочие процессы разработчика

Рабочие процессы разработчика

Класс Awaitable В Unity 6 появился класс Awaitable - лёгкий тип без выделения памяти, специально разработанный для поддержки асинхронных рабочих процессов C# на основе async/await в Unity. Он служит производительной альтернативой корутинам и упрощает написание асинхронного кода, который корректно встраивается в покадровый цикл обновления Unity.

C#
using UnityEngine;
using System.Threading.Tasks;
public class LogWithDelay : MonoBehaviour {
    private async void Start() {
        Debug.Log(“Message 1”);
        await Task.Delay(1000);
        // Wait 1 second Debug.Log(“Message 2”);

        await Task.Delay(1000);
        // Wait another second

    }
}

©2025UnityTechnologies

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

Атрибуты, влияющие на поля окна Inspector

В C# имена атрибутов заключаются в квадратные скобки. Ниже перечислены некоторые распространённые атрибуты, которые можно добавлять в скрипты.

Атрибут

Описание

Пример

SerializeField

Заставляет Unity сериализовать закрытое поле и делает его видимым в окне Inspector.

[SerializeField]

Этот атрибут задаёт допустимый диапазон для переменной float или int. В окне Inspector поле отображается в виде ползунка.

[Range(1,6)]

Скрывает переменную в окне Inspector, не отключая её сериализацию.

[HideInInspector]

Range

HideInInspector

©2025UnityTechnologies

C#
private GameObject m_myObject;
C#
public int IntegerRange;
[Range(0.2f, 0.8f)] public float m_floatRange;
C#
public Int p = 5;

RequireComponent

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

Примечание. Этот атрибут выполняет проверку только в момент добавления компонента к объекту GameObject.

C#
// PlayerScript requires the GameObject to have a Rigidbody

[RequireComponent(typeof(Rigidbo dy))] public class PlayerScript: Monobehaviour {
    private Rigidbody m_rBody;
    void Start() { m_rBody = GetComponent<Rigidbody>(); }
}

Tooltip

Показывает всплывающую подсказку, когда пользователь наводит указатель мыши на поле в окне Inspector.

C#
public class PlayerScript: Monobehaviour {
    [Tooltip(“Health value between 0 and 100.”)] int m_health = 0;
}

Space

Header

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

C#
// 10 pixel of spacing added int p = 5;
public class PlayerScript: полужирный заголовок Monobehaviour и отступ, помогая упорядочить {
    переменные в окне [Header(“Health Settings”)] Inspector. Применяйте атрибут только к private int m_health = 0;
    первому полю соответствующей private int m_maxHealth = 100;
    группы. [Header(“Shield Settings”)] private int m_shield = 0;
    private int m_maxShield = 0;
}

©2025UnityTechnologies

Multiline

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

C#
public string textToEdit;
[Multiline(20)] public string m_moreTextToEdit;

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

SelectionBase

ColorUsage

©2025UnityTechnologies

Полезен для выбора пустого объекта GameObject, дочерние объекты которого содержат меши. Добавьте этот атрибут к любому компоненту базового объекта. Тогда при выборе объектов в редакторе будет выбран GameObject с атрибутом [SelectionBase], а не его дочерние объекты.

C#
// add this to the base GameObject

Атрибут [ColorUsage] позволяет управлять тем, какие цвета можно выбирать в поле цвета. В зависимости от параметров можно включить HDR и отключить альфа-канал.

public ColorUsageAttribute(bool showAlpha, bool hdr, float minBrightness, float maxBrightness, float minExposureValue, float maxExposureValue);

C#
public class PlayerScript: Monobehaviour { }

RunOnce

Нужно автоматически выполнить функцию лишь один раз при запуске проекта? Простой способ использовать статический метод с атрибутом [RuntimeInitializeOnLoa dMethod]. Он подходит для однократной инициализации проекта, например загрузчика, как показано в примере QuizU.

C#
public RuntimeInitializeOnLoadMeth odAttribute(RuntimeInitializeLoadT ype loadType);

Это лишь малая часть множества доступных атрибутов. Нужно переименовать переменные, не потеряв их значения, или выполнить определённую логику без пустого объекта GameObject? Можно даже создать собственный PropertyAttribute и определить пользовательские атрибуты для переменных скрипта. Полный список атрибутов приведён в Scripting API.

Создавайте пользовательские окна и окна Inspector Одна из самых мощных возможностей Unity - расширяемый редактор. Для создания интерфейсов редактора, включая пользовательские окна и окна Inspector, рекомендуется использовать пакет UI Toolkit.

Пользовательский редактор изменяет представление скрипта MyPlayer в окне Inspector.

Подробнее о реализации пользовательских скриптов редактора с помощью UI Toolkit или IMGUI см. в разделе «Создание пользовательских интерфейсов (UI)». Краткое введение в UI Toolkit доступно в руководстве «Начало работы со скриптами редактора».

©2025UnityTechnologies

Создавайте пользовательские меню Unity позволяет легко настраивать меню редактора и их пункты с помощью атрибута MenuItem. Его можно применить к любому статическому методу в скриптах. Если некоторые функции проекта используются часто, оформите их как пункты меню. Так можно создать простой пользовательский интерфейс всего с одним модификатором PropertyAttribute.

Атрибут MenuItem создаёт простой интерфейс для вызова статического метода Take Screenshot.

Ускорьте переход в режим Play При переходе в режим Play проект запускается так же, как готовая сборка. Все изменения, внесённые в редакторе в режиме Play, сбрасываются после выхода из этого режима.

При каждом переходе в режим Play Unity выполняет два важных действия: - Domain Reload: Unity сохраняет, выгружает и заново создаёт состояние скриптов. - Scene Reload: Unity уничтожает сцену и загружает её заново. . По мере усложнения скриптов и сцен эти два действия занимают всё больше времени.

Если дальнейшие изменения скриптов не планируются, параметры Enter Play Mode Settings (Edit > Project Settings > Editor) помогут сократить время компиляции. Unity позволяет отключить Domain Reload, Scene Reload или оба действия, что ускоряет вход в режим Play и выход из него.

©2025UnityTechnologies

Помните: если вы планируете продолжать изменять скрипты, Domain Reload необходимо снова включить. Аналогично, после изменения иерархии сцены следует снова включить Scene Reload. Иначе возможны неожиданные результаты.

Результат отключения параметров Reload Domain и Reload Scene

Настраивайте стандартные шаблоны скриптов Если при создании каждого нового скрипта вы вносите одни и те же изменения например, сразу добавляете пространство имён или удаляете функцию события Update, - настройте исходный шаблон скрипта. Это сократит число нажатий клавиш и обеспечит единообразие в команде.

При создании нового скрипта или шейдера Unity использует шаблон из папки %EDITOR_PATH%\Data\Resources\ScriptTemplates: —

Windows: C:\Program Files\Unity\Editor\Data\Resources\ScriptTemplates

- Mac: /Applications/Hub/Editor/[version]/Unity/Unity.app/Contents/Resources/ScriptTemplates Также доступны шаблоны шейдеров, других скриптов поведения и определений сборок. Чтобы использовать шаблоны скриптов только в конкретном проекте, создайте папку Assets/ScriptTemplates и скопируйте в неё шаблоны, которые должны переопределить стандартные.

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

Доставляйте игрокам контент по запросу с помощью Addressables Addressables и Asset Bundles - мощные средства, позволяющие разделить игру на логические блоки. Эти блоки можно экспортировать отдельно и при необходимости добавлять к основному исполняемому файлу.

©2025UnityTechnologies

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

До инициализации системы Addressables в проекте Unity

Если вы только начинаете работать с Addressables, ознакомьтесь со страницей Get started в документации Unity. Советы по эффективному управлению ассетами: - Используйте Addressables с самого начала разработки и регистрируйте каждый новый ассет как Addressable. - Группируйте ассеты по тому, насколько часто они загружаются и используются вместе, а не по типу. Это улучшает использование памяти во время выполнения, сокращает время запуска и, как следствие, способствует удержанию игроков. - Старайтесь создавать небольшие пакеты: это сокращает цепочки зависимостей и снижает расход памяти во время выполнения. Подробнее см. в статье «Эффективное управление ассетами в Unity с помощью Addressables».

Создавайте условно компилируемый код с помощью директив препроцессора Платформозависимая компиляция позволяет условно компилировать и выполнять код в зависимости от целевой платформы, версии Unity или скриптового бэкенда. Это полезно при разработке кроссплатформенного кода, оптимизации поведения для конкретных устройств и работе с API, доступными только в определённых версиях.

©2025UnityTechnologies

При тестировании в редакторе можно задавать собственные директивы #define. Откройте панель Other Settings в Player settings и перейдите к параметру Scripting Define Symbols.

Параметр Scripting Define Symbols в разделе Script Compilation

Отделяйте данные от логики с помощью ScriptableObject ScriptableObject помогает поддерживать чистую архитектуру кода, отделяя данные от логики. Благодаря этому проще вносить изменения без нежелательных побочных эффектов, а код становится более тестируемым и модульным. Такие объекты также удобны при совместной работе с художниками и дизайнерами: они могут редактировать игровые данные, не изменяя код. Dragon Crashers демонстрирует типичный сценарий использования. Класс UnitInfoData наследуется от ScriptableObject. Каждый его экземпляр содержит имя игрового персонажа, спрайт и параметры здоровья. Эти данные остаются неизменными в ходе игры, поэтому особенно хорошо подходят для хранения в ScriptableObject.

ScriptableObject определяет объект-контейнер данных.

©2025UnityTechnologies

Атрибут CreateAssetMenu создаёт пункт контекстного меню для генерации ассета ScriptableObject. У каждого игрового персонажа есть дополнительные объекты ScriptableObject для звуковых эффектов и особых способностей.

После создания ассетов в окне Project задайте нужные значения в окне Inspector: Unit Name, Unity Avatar (Sprite) и Total Health.

Задайте значения ассета ScriptableObject в окне Inspector. Во время игры они не изменяются.

Объект GameObject, в данном случае UnitController, может ссылаться на ассет ScriptableObject. Даже если сцена заполнится множеством игровых персонажей, данные ассета ScriptableObject не будут дублироваться, что экономит память.

©2025UnityTechnologies

Объект MonoBehaviour (показанный выше UnitController) ссылается на ассет ScriptableObject с данными проекта.

Экономьте память и поддерживайте порядок с помощью ScriptableObject. Статические данные и настройки достаточно задать в ассете проекта один раз, даже если у вас множество объектов GameObject.

©2025UnityTechnologies

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

По мере роста игры и появления новых типов юнитов просто создавайте дополнительные ассеты ScriptableObject и подставляйте нужные. Игровые данные можно поддерживать в актуальном состоянии, изменяя централизованно хранящиеся ассеты. ScriptableObject не заменяют хранение постоянных данных в файлах сохранения приложения, где данные могут изменяться во время игры. Этот подход лучше подходит для статических игровых настроек и значений по умолчанию. В отличие от разбора JSON или XML, чтение ассета ScriptableObject не создаёт мусора (и к тому же выполняется быстрее). Дополнительные материалы о ScriptableObject: - Создание модульной архитектуры игры в Unity с помощью ScriptableObject - Демонстрационный проект ScriptableObjects Paddle Ball - Документация по ScriptableObject

Повышайте модульность скриптов с Assembly Definitions Сборка - это скомпилированная библиотека кода C#, объединяющая связанные типы и ресурсы в единую логическую единицу. В Unity сборками можно управлять с помощью файлов Assembly Definition (.asmdef). Разделение скриптов на пользовательские сборки повышает модульность и возможность повторного использования, а также сокращает время компиляции. При этом скрипты не добавляются автоматически в стандартные сборки, а доступ к другим скриптам можно ограничить. Если вы упорядочиваете проект с помощью Assembly Definitions, но скрипты Editor попадают в билды, создайте Assembly Definition в папке Editor и укажите для неё только платформу Editor.

©2025UnityTechnologies

Настройки Assembly Definitions в Inspector

©2025UnityTechnologies

Переходите на Input System Если вы ещё не перешли, обратите внимание на пакет Input System - более новую и гибкую систему по сравнению с Input Manager, которая позволяет управлять содержимым Unity с помощью устройств ввода любого типа. Её называют пакетом Input System или просто Input System. Она также поддерживает переназначаемое управление, ассеты Input Action и более чёткое разделение логики ввода и игрового процесса, что даёт заметные преимущества перед устаревшей системой.

Для начала ознакомьтесь со следующими материалами: - Ускоренное прототипирование мобильных игр с Input System в Unity 6 | Unite 2024 - Начало работы с Input System - Серия из семи видеоуроков по Unity Input System

Инструменты профилирования Оптимизируйте использование памяти с помощью Memory Profiler Memory Profiler позволяет фиксировать и анализировать использование памяти в проекте, чтобы выявлять утечки, уменьшать пиковое потребление и оптимизировать производительность во время выполнения. Делайте снимки памяти в ключевые моменты - например, при загрузке сцен или после длительных игровых сеансов - и сравнивайте их, чтобы находить объекты, которые не освобождаются должным образом. Создавая ресурсы в коде, возьмите за правило присваивать им имена для Memory Profiler. Кроме того, не забывайте освобождать всё, что выделили, чтобы избежать утечек.

Снимок памяти в Memory Profiler

©2025UnityTechnologies

Находите критичный код с помощью ProfilerMarker Вместо просмотра лишь общих данных о производительности под стандартными маркерами вроде BehaviourUpdate можно изолировать конкретные функции и точно измерить время их выполнения. С помощью ProfilerMarker отмечайте блоки кода скриптов, чтобы повысить детализацию профилирования. Результаты отображаются в CPU Profiler и могут записываться с помощью Unity Recorder. Так вы получите подробную картину затрат времени в конкретных участках кода, что упрощает поиск узких мест и оптимизацию.

C#
using UnityEngine;
using Unity.Profiling;
public class UnityTips : MonoBehaviour {
    private static readonly ProfileMarker SetupProfileMarker = new ProfileMarker(“Setup”);
    private static readonly ProfileMarker ExpensiveProfileMarker = new ProfileMarker(“Expensive”);
    public void UpdateLogic() {
        SetupProfileMarker.Begin();
        on...
C#
// Setup your performance heavy things, Initializers, and so SetupProfileMarker.End();

using (ExpensiveProfileMarker.Auto()) { //This starts and ends automatically // More expensive things here.

Проведите аудит производительности проекта Используйте Project Auditor (доступный как пакет начиная с Unity 6.1), чтобы анализировать производительность проекта, соблюдать рекомендации и выявлять возможные проблемы и узкие места. Всего за несколько щелчков можно просканировать весь проект и получить подробный отчёт о проблемах: затратных вызовах скриптов, неиспользуемых ассетах, чрезмерном количестве сущностей и многом другом.

©2025UnityTechnologies

Представление Summary в Project Auditor

Сформированные отчёты группируются по степени серьёзности: ошибки, предупреждения и информационные замечания. Благодаря этому легко сначала сосредоточиться на ошибках и предупреждениях, например на чрезмерном выделении памяти или слишком частой сборке мусора. Обычно рекомендуется запускать Project Auditor на ключевых этапах разработки например, перед контрольными точками, бета-выпусками и финальными билдами. Это позволяет заранее выявить узкие места производительности, неиспользуемые ассеты и устаревший код, не давая проблемам накапливаться по мере роста проекта.

Project Auditor можно настроить с помощью пользовательских правил и фильтров. Например, исключить из анализа заведомо неиспользуемые или экспериментальные скрипты и ассеты либо создать отдельные правила для целевых платформ, разрешения, сжатия текстур и других параметров проекта, чтобы они соответствовали установленным «бюджетам».

©2025UnityTechnologies

Кривые анимации Управляйте интерполяцией с помощью пользовательской функции lerp По умолчанию Mathf.Lerp(a, b, t) ограничивает коэффициент интерполяции t диапазоном от 0 до 1, поэтому результат не выходит за пределы значений a и b. Если требуется выход за верхнюю (t > 1) или нижнюю (t < 0) границу, используйте Mathf.LerpUnclamped(a, b, t). Эта функция даёт полный контроль над интерполяцией и позволяет создавать такие эффекты, как экстраполяция или движение по инерции.

C#
using UnityEngine;
public class LerpComparison : MonoBehaviour {
    [SerializeField] private float start = 0f;
    [SerializeField] private float end = 10f;
    [SerializeField] private float t = 1.5f;
    private void Start() {
        // Clamps t to

        [0, 1] float clamped = Mathf.Lerp(start, end, t);
        // Uses full t value float unclamped = Mathf.LerpUnclamped(start, end, t);

        // Outputs 10 Debug.Log($”Mathf.Lerp: {clamped}

        (t = {t})”);
        // Outputs 15 Debug.Log($”Mathf.LerpUnclamped: {unclamped}

        (t = {t})”);
    }
}

Пример использования пользовательской линейной интерполяции в Unity

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

Кривые анимации можно редактировать в Inspector как открытые или сериализованные переменные. Их можно сохранять, экспортировать и загружать как в режиме редактирования, так и во время выполнения. Редактируемые касательные позволяют управлять формой кривой между ключами.

©2025UnityTechnologies

Свойство Animation Curve в Inspector: щелчок по нему открывает Curve Editor, где можно изменить кривую и сохранить её в собственной библиотеке, выбрав значок шестерёнки.

Дополнительные практические советы и примеры использования AnimationCurve в проекте приведены в публикации блога «Animation Curves - универсальный рычаг дизайна».

Снижайте нагрузку с помощью пулов объектов Пул объектов - это паттерн проектирования, который помогает повысить производительность, уменьшая нагрузку на CPU от многократных вызовов создания и уничтожения объектов. Вместо этого уже существующие GameObject можно использовать повторно. Способ применения пулов объектов зависит от конкретного приложения. Общее полезное правило: профилируйте код всякий раз, когда создаёте большое количество экземпляров объектов, поскольку это может вызвать пик сборки мусора. Если вы обнаружили значительные пики, из-за которых игровой процесс может начать подтормаживать, рассмотрите применение пула объектов. Учтите, что управление несколькими жизненными циклами пулов усложняет кодовую базу. Кроме того, если создать слишком много пулов заранее, можно зарезервировать память, которая в действительности игре не нужна.

Подробнее о пулах объектов рассказывается в электронной книге «Совершенствуйте код с помощью паттернов проектирования и SOLID» и в сопутствующем демонстрационном проекте, бесплатно доступном в Unity Asset Store.

Дополнительные материалы - Руководство по стилю C# для чистого и масштабируемого игрового кода (издание для Unity 6)

- Справочник гейм-дизайнера Unity - Создание модульной архитектуры игры в Unity с помощью ScriptableObject - Эффективное управление ассетами в Unity с помощью Addressables - Что нужно знать о Build Profiles в Unity 6

©2025UnityTechnologies