← Назад к вопросам

Для чего используются SerializedObject, SerializedProperty, AssetDatabase?

1.8 Middle🔥 121 комментариев
#Ресурсы и ассеты

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

SerializedObject, SerializedProperty и AssetDatabase: ключевые инструменты редактора Unity

В Unity-разработке, особенно при создании кастомных инспекторов, редакторских окон и инструментов, SerializedObject, SerializedProperty и AssetDatabase образуют триаду фундаментальных классов, обеспечивающих работу с данными внутри редактора Unity. Их основное назначение — предоставить безопасный, унифицированный и функциональный способ чтения, модификации и сохранения сериализованных данных объектов и ассетов, полностью интегрированный с системой Undo/Redo и автоматическим обновлением инспектора.


SerializedObject: контейнер для управления сериализованными данными

SerializedObject — это представление одного или нескольких объектов Unity (наследников UnityEngine.Object) в виде их сериализованных данных. Он выступает в роли посредника между C#-скриптом (например, кастомным редактором) и фактическими полями объекта в памяти.

  • Основная цель: Обеспечить безопасное изменение свойств объектов в редакторе с поддержкой операций Undo (отмена) и автоматическим уведомлением об изменениях.
  • Ключевые сценарии использования:
    *   Создание кастомных инспекторов (`Editor`-классов) для компонентов или ScriptableObject.
    *   Редактирование нескольких выделенных объектов одновременно.
    *   Обход сложной иерархии данных объекта (массивы, вложенные классы).
  • Типичный workflow:
    1.  Создать `SerializedObject` из целевого объекта.
    2.  Получить `SerializedProperty` для нужного поля.
    3.  Использовать методы `SerializedObject.Update()` и `ApplyModifiedProperties()` для синхронизации.

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(MyComponent))]
public class MyComponentEditor : Editor
{
    private SerializedProperty _healthProperty;
    private SerializedProperty _nameProperty;

    void OnEnable()
    {
        // Создаем SerializedObject на основе целевого объекта (автоматически предоставляется базовым Editor)
        // serializedObject уже создан базовым классом Editor
        // Находим сериализованные свойства по имени поля в скрипте
        _healthProperty = serializedObject.FindProperty("health");
        _nameProperty = serializedObject.FindProperty("unitName");
    }

    public override void OnInspectorGUI()
    {
        // Обновляем сериализованное представление, чтобы отразить текущие значения объекта
        serializedObject.Update();

        // Редактируем свойства с помощью встроенных методов EditorGUI
        EditorGUILayout.PropertyField(_nameProperty);
        EditorGUILayout.IntSlider(_healthProperty, 0, 100);

        // Применяем изменения ко всем объектам, на которые ссылается SerializedObject,
        // регистрируем операцию для Undo и отмечаем объекты как "грязные"
        if (serializedObject.ApplyModifiedProperties())
        {
            Debug.Log("Значения изменены и сохранены!");
        }
    }
}

SerializedProperty: "указатель" на конкретное поле

SerializedProperty — это представление отдельного сериализованного поля (property) внутри SerializedObject. Это может быть примитив (int, float, string), ссылка на UnityEngine.Object, массив (SerializedProperty.isArray == true) или поле вложенного класса.

  • Основная цель: Предоставить унифицированный API для доступа и модификации значения поля, его атрибутов (например, [Range]) и мета-информации, независимо от его типа.
  • Ключевые особенности:
    *   **Обход иерархии:** Позволяет "гулять" по свойствам-детям (`SerializedProperty.Copy()`, `.GetArrayElementAtIndex()`, `.FindPropertyRelative()`).
    *   **Безопасность:** Изменения через `SerializedProperty` автоматически интегрируются с системой `SerializedObject`.
    *   **Универсальность:** Использует методы `.intValue`, `.floatValue`, `.objectReferenceValue`, `.stringValue`, `.vector3Value` и т.д., в зависимости от типа свойства (`propertyType`).
  • Пример работы с массивом:
SerializedProperty itemsArray = serializedObject.FindProperty("items");
EditorGUILayout.LabelField("Элементы:", EditorStyles.boldLabel);

for (int i = 0; i < itemsArray.arraySize; i++)
{
    SerializedProperty element = itemsArray.GetArrayElementAtIndex(i);
    EditorGUILayout.PropertyField(element, new GUIContent($"Элемент {i}"));
}

AssetDatabase: менеджер файловой системы проекта Unity

AssetDatabase — это статический класс, который предоставляет API для работы с ассетами (файлами) внутри папки Assets проекта. Он абстрагирует низкоуровневые файловые операции, обеспечивая их корректность с точки зрения Unity (обновление мета-файлов, импорт, ре-импорт, кеширование).

  • Основная цель: Управление жизненijным циклом ассетов в редакторе: создание, загрузка, сохранение, переименование, перемещение, поиск.
  • Ключевые функции:
    *   **Создание ассетов:** `AssetDatabase.CreateAsset()`, `AssetDatabase.GenerateUniqueAssetPath()`.
    *   **Загрузка и поиск:** `AssetDatabase.LoadAssetAtPath()`, `AssetDatabase.FindAssets()`.
    *   **Модификация файлов:** `AssetDatabase.Refresh()` (критически важный метод после скриптовой работы с файлами), `AssetDatabase.SaveAssets()`, `AssetDatabase.ImportAsset()`.
    *   **Работа с метаданными:** `AssetDatabase.GetDependencies()`, `AssetDatabase.CopyAsset()`, `AssetDatabase.MoveAsset()`.
  • Пример создания ScriptableObject через редакторный скрипт:
using UnityEditor;
using UnityEngine;

public class AssetCreator
{
    [MenuItem("Tools/Create MyConfig")]
    static void CreateConfigAsset()
    {
        // Создаем экземпляр ScriptableObject в памяти
        MyScriptableObject config = ScriptableObject.CreateInstance<MyScriptableObject>();
        config.someValue = 42;

        // Генерируем уникальный путь для сохранения
        string path = EditorUtility.SaveFilePanelInProject(
            "Сохранить конфиг",
            "NewConfig",
            "asset",
            "Выберите место для сохранения"
        );

        if (!string.IsNullOrEmpty(path))
        {
            // Создаем ассет на диске и сохраняем файл
            AssetDatabase.CreateAsset(config, path);
            AssetDatabase.SaveAssets(); // Фиксируем изменения в БД ассетов
            AssetDatabase.Refresh();    // Обновляем окно Project
            EditorUtility.FocusProjectWindow();
            Selection.activeObject = config; // Выделяем созданный ассет
        }
    }
}

Синергия и итог

Эти три инструмента часто используются вместе:

  1. AssetDatabase используется для поиска, загрузки или создания ассета (например, ScriptableObject).
  2. Для модификации полей этого загруженного ассета в редакторском коде создается SerializedObject.
  3. Через SerializedObject получаются конкретные SerializedProperty для редактирования.
  4. После применения изменений (ApplyModifiedProperties()) может потребоваться вызов AssetDatabase.SaveAssets() для гарантированного сохранения ассета на диск.

Таким образом, SerializedObject и SerializedProperty — это инструменты для безопасного редактирования данных в памяти с полной поддержкой редакторского конвейера Unity, а AssetDatabase — это инструмент для управления файлами этих данных на диске в рамках проекта. Их правильное использование — признак профессионального подхода к созданию редакторских расширений в Unity.

Для чего используются SerializedObject, SerializedProperty, AssetDatabase? | PrepBro