Введение
В этой статье я покажу, как правильно пользоваться классом ScriptableObject в Unity. Мы создадим небольшую игру для наглядности, в которой игрок сможет управлять персонажем с различными параметрами, навыками и инвентарем. Мы рассмотрим создание и использование ScriptableObject для хранения данных. В конце вы найдете плюсы и минусы использования данного метода.
Введение в ScriptableObject
Что такое ScriptableObject и зачем он нужен?
ScriptableObject - это класс в Unity, который позволяет хранить данные отдельно от игровых объектов. Это особенно полезно для управления данными, которые часто изменяются или используются многократно. Основные случаи использования включают:
• Хранение игровых данных (например, параметры персонажей, настройки уровней).
• Управление состоянием игры.
• Создание редакторов и инструментов.
Пример использования ScriptableObject в Unity
Общий обзор
Мы создадим мини-игру, где игрок может управлять персонажем с различными параметрами, навыками и инвентарем. Весь функционал будет построен на ScriptableObject для хранения данных персонажей, навыков и предметов.
Шаг 1: Создание ScriptableObject для параметров персонажа
Начнем с создания класса ScriptableObject для хранения параметров персонажа.
using UnityEngine;
[CreateAssetMenu(fileName = "NewCharacterStats", menuName = "Character Stats")]
public class CharacterStats : ScriptableObject
{
[SerializeField] private string _characterName;
[SerializeField] private int _health;
[SerializeField] private int _attackPower;
[SerializeField] private int _defense;
[SerializeField] private Skill[] _skills;
public string CharacterName => _characterName;
public int Health => _health;
public int AttackPower => _attackPower;
public int Defense => _defense;
public Skill[] Skills => _skills;
}
Пояснение к коду:
• CreateAssetMenu позволяет создавать объекты через контекстное меню в Unity Editor.
• Параметры персонажа включают имя, здоровье, силу атаки, защиту и массив навыков.
Шаг 2: Создание ScriptableObject для навыков
Теперь создадим ScriptableObject для хранения данных о навыках.
using UnityEngine;
[CreateAssetMenu(fileName = "NewSkill", menuName = "Skill")]
public class Skill : ScriptableObject
{
[SerializeField] private string _skillName;
[SerializeField] private int _power;
[SerializeField] private float _cooldown;
public string SkillName => _skillName;
public int Power => _power;
public float Cooldown => _cooldown;
}
Пояснение к коду:
• CreateAssetMenu позволяет создавать объекты через контекстное меню в Unity Editor.
• Данные о навыке включают имя, силу и время перезарядки.
Шаг 3: Создание ScriptableObject для предметов
Создадим ScriptableObject для хранения данных о предметах.
using UnityEngine;
[CreateAssetMenu(fileName = "NewItem", menuName = "Inventory Item")]
public class InventoryItem : ScriptableObject
{
[SerializeField] private string _itemName;
[SerializeField] private Sprite _itemIcon;
[SerializeField] private int _itemID;
public string ItemName => _itemName;
public Sprite ItemIcon => _itemIcon;
public int ItemID => _itemID;
}
Пояснение к коду:
• CreateAssetMenu позволяет создавать объекты через контекстное меню в Unity Editor.
• Данные о предмете включают имя, иконку и уникальный идентификатор.
Шаг 4: Использование ScriptableObject в MonoBehaviour
Создадим MonoBehaviour для управления персонажем, который будет использовать ScriptableObject для хранения параметров, навыков и инвентаря.
using System.Collections.Generic;
using UnityEngine;
public class Character : MonoBehaviour
{
[SerializeField] private CharacterStats _stats;
[SerializeField] private List<InventoryItem> _inventory = new();
public void AddItemToInventory(InventoryItem item)
{
_inventory.Add(item);
Debug.Log($"Added item: {item.ItemName}");
}
private void Start()
{
Debug.Log($"Name: {_stats.CharacterName}, Health: {_stats.Health}, Attack: {_stats.AttackPower}, Defense: {_stats.Defense}");
foreach (var skill in _stats.Skills)
{
Debug.Log($"Skill: {skill.SkillName}, Power: {skill.Power}, Cooldown: {skill.Cooldown}");
}
}
}
Пояснение к коду:
• Переменные _stats и _inventory хранят ссылки на объекты ScriptableObject.
• Метод Start выводит параметры персонажа и его навыки в консоль.
• Метод AddItemToInventory добавляет предмет в инвентарь персонажа.
3. Создание мини-игры
Общий обзор
Создадим сцену, на которой игрок сможет управлять персонажем, собирать предметы, использовать навыки и видеть их в инвентаре.
Шаг 1: Создание персонажа и привязка параметров
В Unity создадим префаб персонажа и привяжем к нему параметры, используя ScriptableObject.
1. Создайте GameObject для персонажа.
2. Добавьте компонент Character и привяжите CharacterStats через инспектор.
Шаг 2: Создание предметов и привязка к инвентарю
Добавим несколько предметов в сцену и настроим их взаимодействие с персонажем.
1. Создайте несколько экземпляров InventoryItem.
2. Добавьте их в список inventory у компонента Character.
-
Создайте скилы и добавьте в статы игрока.
Шаг 3: Реализация использования навыков
Добавим возможность использования навыков персонажем.
using System.Collections;
using UnityEngine;
public class SkillUser : MonoBehaviour
{
[SerializeField] private Character _character;
private bool _isAbleToUseSkill = true;
private void Update()
{
if (_isAbleToUseSkill)
{
for (int i = 0; i < _character.Stats.Skills.Length; i++)
{
if (Input.GetKeyDown(KeyCode.Alpha1 + i))
{
UseSkill(i);
}
}
}
}
private void UseSkill(int index)
{
if (index < _character.Stats.Skills.Length)
{
Skill skill = _character.Stats.Skills[index];
Debug.Log($"Using skill: {skill.SkillName}");
StartCoroutine(Cooldown(skill));
}
}
private IEnumerator Cooldown(Skill skill)
{
_isAbleToUseSkill = false;
Debug.Log($"Skill {skill.SkillName} on cooldown for {skill.Cooldown} seconds.");
yield return new WaitForSeconds(skill.Cooldown);
Debug.Log($"Skill {skill.SkillName} is ready to use again.");
_isAbleToUseSkill = true;
}
}
Пояснение к коду:
• Компонент SkillUser управляет использованием навыков персонажа.
• Метод UseSkill активирует навык и запускает перезарядку.
Добавьте этот скрипт персонажу и перенесите компонент Character в соответствующее поле
Теперь можно запустить сцену и проверить работоспособность нашей мини-игры через консоль и есть нам понравится результат, добавлять визуальную реализацию.
P.s.
Я специально не стал писать логику для работы с предметами из инвентаря, чтобы не загромождать туториал лишней инфой, все таки статья про другое)
Если вам вдруг интересно, пишите в комментария "Доделай игру" и я добавлю оставшийся функционал
4. Преимущества и недостатки ScriptableObject
Преимущества
• Удобство управления данными: Разделение данных от логики, упрощение изменения параметров.
• Повторное использование: Легкое использование одного и того же объекта в разных местах проекта.
• Снижение загрузки памяти: ScriptableObject загружаются только один раз и могут быть использованы многократно.
• Простота тестирования: Легкость тестирования и отладки данных.
Недостатки
• Ограниченная поддержка сценариев: Не подходит для всех типов данных и логики.
• Необходимость понимания работы Unity Editor: Требуется знание работы с редактором и ScriptableObject.
• Нет обновлений в реальном времени: Изменения в ScriptableObject не обновляются автоматически в связанных объектах.
5. Заключение
Мы рассмотрели, как использовать ScriptableObject в Unity для создания более сложной мини-игры с управлением персонажем, его навыками и инвентарем. ScriptableObject предоставляет удобный способ управления данными, улучшая архитектуру и производительность проектов. Попробуйте внедрить этот подход в своих проектах и оцените его преимущества.
Если тебе понравилась статья, обязательно голосуй за нее! Так я пойму что тебе она понравилась и рассмотрю другие тематики, связанные с Unity!
VitalyZaborov
Когда вам, чтобы поменять хп у сотни врагов в вашей игре, нужно выбрать каждого персонально и изменить поле в редакторе - это не удобная работа с данными. Достоинства ScriptableObject совершенно не в этом, а в том, что его полями могут быть не простые типы, а сущности движка: спрайты, префабы, прочие ассеты и другие SO.
Например, вам нужно создать описание персонажа, которое объединит его префаб, спрайт иконки и контроллер анимации. Вот тут без SO не обойтись. Можно, конечно, хранить эти ассеты в Resources с определёнными именами, но такой способ имеет много минусов и разработчиками движка не рекоментдуется.
Данные из простых типов (например, характеристики персонажа) гораздо удобнее хранить в обычной экселевской таблице (или в каком-то удобном вам текстовом формате) и уже оттуда генерить в движок. Тогда эти данные легко массово редактировать и их можно мержить.
ArtemiZ_GD Автор
Спасибо за отзыв)
В общем то вы правы, но сотни врагов будут не в каждой игре, следовательно нет надобности всегда работать с таблицами. А вот в мое случае у персонажа есть еще и набор скилов, которые вы не сможете таким образом настраивать.
Нестандартные типы данных я как раз таки показал в статье.
shai_hulud
Или в специализированном инструменте для этого - статичной БД. https://assetstore.unity.com/packages/tools/visual-scripting/charon-game-data-editor-95117