Как правильно применять ScriptableObject в Unity

Введение

В этой статье я покажу, как правильно пользоваться классом 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 _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 через инспектор.

Создание ScriptableObject

Создание ScriptableObject

Настройка ScriptableObject

Настройка ScriptableObject

Добавление статов игроку

Добавление статов игроку

Шаг 2: Создание предметов и привязка к инвентарю

Добавим несколько предметов в сцену и настроим их взаимодействие с персонажем.

1. Создайте несколько экземпляров InventoryItem.

2. Добавьте их в список inventory у компонента Character.

69542b1a8f779168708c959bcdbb4969.png

  1. Создайте скилы и добавьте в статы игрока.

    Создание скилов

    Создание скилов

    Добавление скилов игроку

    Добавление скилов игроку

Шаг 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!

© Habrahabr.ru