Note
ScriptableObject — это специальный тип класса в Unity, который позволяет хранить большие объёмы данных независимо от игровых объектов (GameObject).
В отличие от MonoBehaviour, он не привязан к сцене и не требует наличия объекта в иерархии.
Вы можете создать ScriptableObject как файл-ассет в проекте (в окне Project) и хранить в нём:
- числа, строки, булевы значения
- списки и массивы
- ссылки на другие ассеты (текстуры, звуки, модели, префабы)
- пользовательские классы и структуры
Создайте ассет PlayerStats.asset, в котором лежат:
maxHealth = 100, moveSpeed = 5.5, jumpForce = 12, weaponPrefab (ссылка на префаб меча).
Один и тот же 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 и читаете оттуда данные.
Многие разработчики используют синглтоны (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!
- Создайте C# скрипт, унаследованный от
ScriptableObject:
using UnityEngine;
[CreateAssetMenu(fileName = "NewItem", menuName = "Game/Item")]
public class ItemSO : ScriptableObject
{
public string itemName;
public int value;
public Sprite icon;
}- В редакторе: правой кнопкой в окне
Project→Create→Game/Item→ появится файл.asset. - Заполните поля в инспекторе.
- Используйте в любом
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-заглушку для тестов, не меняя основной код.