Skip to content

Latest commit

 

History

History
118 lines (93 loc) · 6.27 KB

File metadata and controls

118 lines (93 loc) · 6.27 KB

🧠 ScriptableObject в Unity: Хранение данных, конфигурация, замена синглтонов

Note

ScriptableObject — это специальный тип класса в Unity, который позволяет хранить большие объёмы данных независимо от игровых объектов (GameObject). В отличие от MonoBehaviour, он не привязан к сцене и не требует наличия объекта в иерархии.


🎯 Основные возможности

1. 📦 Хранение данных

Вы можете создать ScriptableObject как файл-ассет в проекте (в окне Project) и хранить в нём:

  • числа, строки, булевы значения
  • списки и массивы
  • ссылки на другие ассеты (текстуры, звуки, модели, префабы)
  • пользовательские классы и структуры

Пример:

Создайте ассет PlayerStats.asset, в котором лежат:
maxHealth = 100, moveSpeed = 5.5, jumpForce = 12, weaponPrefab (ссылка на префаб меча).

2. ⚙️ Конфигурация (настройки)

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

Пример:

Вы создали EnemyConfig.asset с полями: health, damage, color, speed.
Теперь можете создать 3 разных файла:

  • GoblinConfig.asset (health=30, damage=5)
  • OrcConfig.asset (health=80, damage=15)
  • TrollConfig.asset (health=150, damage=25)

Затем в компоненте врага (MonoBehaviour) вы просто ссылаетесь на нужный EnemyConfig и читаете оттуда данные.

3. 🔁 Замена синглтонов (Singletons)

Многие разработчики используют синглтоны (public static GameManager Instance) для глобального доступа к данным.

Недостатки синглтонов:

  • сложно тестировать
  • привязаны к сцене
  • теряются при перезагрузке сцены
  • жесткая связь между системами

Решение: ScriptableObject как глобальный сервис (или «менеджер событий/данных»).
Вы создаёте экземпляр ScriptableObject в проекте и ссылаетесь на него из любых скриптов через public поле (сериализация).

Это даёт:

  • слабую связанность (loose coupling)
  • возможность заменять реализации (например, подменять конфиг для тестов)
  • сохранение данных между сценами (если объект не сбрасывать)

Пример глобального хранилища:

// GameDataSO.cs
[CreateAssetMenu(fileName = "GameData", menuName = "Game/GameData")]
public class GameDataSO : ScriptableObject
{
    public int score;
    public int lives;
    public void AddScore(int value) { score += value; }
}

Любой скрипт может получить доступ к этим данным через ссылку на GameDataSO, подставленную в инспекторе.
Никакого Instance!


🛠️ Как создать ScriptableObject

  1. Создайте C# скрипт, унаследованный от ScriptableObject:
using UnityEngine;

[CreateAssetMenu(fileName = "NewItem", menuName = "Game/Item")]
public class ItemSO : ScriptableObject
{
    public string itemName;
    public int value;
    public Sprite icon;
}
  1. В редакторе: правой кнопкой в окне ProjectCreateGame/Item → появится файл .asset.
  2. Заполните поля в инспекторе.
  3. Используйте в любом MonoBehaviour:
public class ItemPicker : MonoBehaviour
{
    public ItemSO itemData; // перетащите ассет в инспекторе
    void Start()
    {
        Debug.Log(itemData.itemName);
    }
}

✅ Преимущества перед другими подходами

Подход Плюсы Минусы
Поля в MonoBehaviour Просто Данные копируются в каждый объект, сложно менять массово
Синглтон Глобальный доступ Жёсткая связь, проблемы с тестами
ScriptableObject Конфигурация ассетами, замена синглтонов, слабая связность Нужно вручную сбрасывать состояние при перезапуске игры

🧪 Особенности и советы

  • 🧹 Сброс состояния: После завершения игры значения полей ScriptableObject (например, score) остаются изменёнными, потому что ассет сохраняется на диск. Для сброса создайте метод Reset() и вызывайте его при старте игры.
  • 🧩 События: ScriptableObject можно использовать как шину событий (Event Channel) — например, VoidEventSO, IntEventSO. Разные системы подписываются на событие, не зная друг о друге.
  • 🧪 Тестирование: Вы можете создать отдельный ScriptableObject-заглушку для тестов, не меняя основной код.

⭐ Если этот проект был полезен, поставьте звезду на GitHub!