ScriptableObject
ScriptableObject — это сериализированный тип Unity, полученный из UnityEngine.ObjectКак и в случае MonoBehaviour, вы не создаёте экземпляр класса ScriptableObject напрямую, а описываете собственные классы C#, наследующие его, и затем создаёте экземпляры этих классов — обычно через Ассеты меню в Unity Editor.
Все экземпляры классов, производных от ScriptableObject обычно называют ScriptableObjectsВ отличие от MonoBehaviours, ScriptableObjects не прикреплены к GameObjects в качестве компонентов, но существуют в проекте в качестве активов, независимо от GameObjectsПотому что ScriptableObjects наследовать от UnityEngine.Object, вы можете перетащить или выбрать экземпляры их в поля в Inspector.
Основное значение ScriptableObject является хранилищем данных, но они также могут определять поведение. Обычно ScriptableObjects используется как контейнер для общих данных, используемых несколькими объектами во время выполнения, что может уменьшить использование памяти проекта, избегая копирования значений.
Например, если в вашем проекте есть префаб, который хранит неизменные данные в приложенных MonoBehaviour скриптах, то каждый новый экземпляр префаб получает свою собственную копию данных. Вместо дублирования данных, как это делается выше, вы можете использовать ScriptableObject для хранения данных и затем доступа к ним по ссылке из всех префабы. Это означает, что в памяти есть одна копия данных.
Основные виды использования ScriptableObjects:
- Сохранение и хранение данных во время сессии Редактора. Именно поэтому многие авторские инструменты в Unity, такие как
EditorToolиEditorWindow, происходят отScriptableObject. - Сохранение данных в качестве ассета в проекте для использования во время выполнения.
Полный справочник по всем членам класса ScriptableObject см. в Ссылка на скрипт ScriptableObject.
Создать ScriptableObject
Для создания нового скрипта ScriptableObject самый быстрый способ — использовать предопределенный шаблон скрипта ScriptableObject из меню Ассеты одним из следующих способов:
- В главном меню перейдите в Ассеты > Создать > Скриптирование > и выберите ScriptableObject Script.
- На панели инструментов окна Projectщелкните правой кнопкой мыши, чтобы открыть контекстное меню окна Project, затем выберите Создать > Сценарий > ScriptableObject Сценарий. Вы также можете нажать на знак плюс в окне Project, чтобы открыть меню Создать напрямую.
Так вы получите собственный базовый класс, наследующий UnityEngine.ScriptableObject. Затем вы можете использовать CreateAssetMenu атрибут, чтобы создавать экземпляры этого класса, каждый из которых становится ассетом в вашем проекте.
Пример: создание экземпляра префабы с ScriptableObject
В следующем примере ScriptableObject хранит данные, заданные на этапе разработки, которые затем определяют, где создавать префабы во время выполнения. Сначала создайте в своём Assets папка:
using UnityEngine;
// Use the CreateAssetMenu attribute to allow creating instances of this ScriptableObject from the Unity Editor.
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
public string prefabName;
public int numberOfPrefabsToCreate;
public Vector3[] spawnPoints;
}
С предыдущим скриптом в папке Assets создайте экземпляр нового ScriptableObject, перейдя в Assets > Create > ScriptableObjects > SpawnManagerScriptableObject. Дайте новому экземпляру ScriptableObject понятное имя и измените значения. Чтобы использовать эти значения во время выполнения, необходимо создать новый скрипт, который ссылается на ваш ScriptableObject, в этом случае SpawnManagerScriptableObject, следующим образом:
using UnityEngine;
public class ScriptableObjectManagedSpawner : MonoBehaviour
{
// The GameObject to instantiate.
public GameObject entityToSpawn;
// An instance of the ScriptableObject defined above.
public SpawnManagerScriptableObject spawnManagerValues;
// This will be appended to the name of the created entities and increment when each is created.
int instanceNumber = 1;
void Start()
{
SpawnEntities();
}
void SpawnEntities()
{
int currentSpawnPointIndex = 0;
for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++)
{
// Creates an instance of the prefab at the current spawn point.
GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints[currentSpawnPointIndex], Quaternion.identity);
// Sets the name of the instantiated entity to be the string defined in the ScriptableObject and then appends it with a unique number.
currentEntity.name = spawnManagerValues.prefabName + instanceNumber;
// Moves to the next spawn point index. If it goes out of range, it wraps back to the start.
currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;
instanceNumber++;
}
}
}
Примечание: Имя файла скрипта должно совпадать с именем класса.
Прикрепить предыдущий скрипт к GameObject в вашем Scene. Затем, в Inspector, заполнить Значения Менеджера Спасения поле с новым .asset экземпляр SpawnManagerScriptableObject что вы установили.
Задайте в поле Entity To Spawn любой префаб из папки Assets проекта, затем перейдите в режим Play. Указанный в ScriptableObjectManagedSpawner префаб создаётся со значениями, заданными в экземпляре SpawnManagerScriptableObject.
Если вы работаете со ссылками ScriptableObject в Inspector, вы можете дважды щелкнуть поле ссылки, чтобы открыть Inspector для вашего ScriptableObject. Вы также можете создать пользовательский Inspector для вашего типа, чтобы помочь управлять данными, которые он представляет.
Сохранение изменений в данных ScriptableObject
В Unity Editor вы можете сохранять данные в ScriptableObjects в режимах Редактирования и Воспроизведения. В автономном Проигрывателе во время выполнения вы можете только читать сохраненные данные из ScriptableObject ассетов. Когда вы используете авторские инструменты Редактора или Inspector для модификации ScriptableObject ассета, Unity автоматически записывает данные на диск и они сохраняются между сессиями Редактора.
Однако Unity не сохраняет автоматически изменения в ScriptableObject, сделанные с помощью скрипта в режиме редактирования. В этих случаях вы должны вызвать EditorUtility.SetDirty на ScriptableObject, чтобы убедиться, что система серийного кодирования Unity распознает его как изменённый и сохраняет изменения на диск. Без этого изменения могут не сохраняться между сессиями Редактора.
Ниже приведен простой ScriptableObject для хранения настроек игры:
using UnityEngine;
[CreateAssetMenu(fileName = "GameSettings", menuName = "ScriptableObjects/GameSettingsScriptableObject", order = 2)]
public class GameSettingsScriptableObject : ScriptableObject
{
public int highScore;
}
Создайте новый экземпляр GameSettingsScriptableObject в вашем проекте с помощью Ассеты > Создайте > ScriptableObjects > GameSettingsScriptableObject. Затем, в Inspector, установите значение highScore.
Следующий скрипт Редактора добавляет простое окно с кнопкой для увеличения рекорда на Окно > Game Редактор Настроек.
using UnityEditor;
using UnityEngine;
public class GameSettingsEditor : EditorWindow
{
GameSettingsScriptableObject settings;
// Create a simple Editor Window to modify the high score in the ScriptableObject
// Accessible at Window > Game Settings Editor
[MenuItem("Window/Game Settings Editor")]
public static void ShowWindow()
{
GetWindow<GameSettingsEditor>("Game Settings Editor");
}
void OnGUI()
{
settings = EditorGUILayout.ObjectField("Settings", settings, typeof(GameSettingsScriptableObject), false) as GameSettingsScriptableObject;
if (settings == null) return;
EditorGUILayout.LabelField("High Score", settings.highScore.ToString());
// Click the Increase High Score button to increase the high score by 10
if (GUILayout.Button("Increase High Score"))
{
settings.highScore += 10;
// Call SetDirty to ensure the change is saved
EditorUtility.SetDirty(settings);
// Optional: AssetDatabase.SaveAssets(); // To save immediately
}
}
}
Без вызова EditorUtility.SetDirty в этом примере изменение на highScore появляется в памяти, но если вы закрыли и заново открыли Редактор, значение возвращается к своему предыдущему значению.
Дополнительные ресурсы
ScriptableObjectAPI ссылка- Введение в ScriptableObjects