MVC (Model-View-Controller) — это схема, предполагающая разделение данных приложения, пользовательского интерфейса и управляющей логики на три отдельных компонента, чтобы каждый из них можно было независимо модифицировать. Разработчик Cem Ugur Karacam поделился своим опытом программирования в Unity и коротко рассказал о Scriptable Objects. Мы представляем перевод его статьи, опубликованной на сайте dev.to.

Добро пожаловать в первую часть моего рассказа о реализации MVC в Unity с помощью Scriptable Objects. В этой статье я написал только про основы работы со Scriptable Objects, и в целом текст будет простым и понятным.
Для начала узнаем, что о Scriptable Objects говорят разработчики Unity:
Теперь логично спросить: почему именно Scriptable Objects?
Scriptable Objects — это часть функционала движка Unity, поэтому такие объекты имеют много встроенных возможностей для работы с редактором.
Мне нравится подход, используемый при разработке проектов на Unity. Вы можете создавать собственные инструменты и легко настраивать те, которые установлены по умолчанию. Scriptable Objects заметно расширяют ваши возможности, поскольку позволяют делать пользовательские контейнеры для данных и хранить их как ассеты в проекте.

Изображение выше — это пример использования Scriptable Object в Unity. Один файл .asset, созданный в проекте, может содержать информацию, необходимую для работы нескольких систем, и обеспечивать сохранение их настроек. Если хотите узнать больше, на YouTube есть отличное видео с презентацией про SO (Scriptable Object) под названием «Свержение тирании MonoBehaviour в выдающейся революции Scriptable Object» (Overthrowing the MonoBehaviour Tyranny in a Glorious Scriptable Object Revolution).

Еще один отличный пример показан выше. Здесь игровые объекты ссылаются на объект инвентаря (Inventory), а система сохранения (Save System) управляет ими всеми. Это изображение из другой прекрасной лекции «Архитектура игры со Scriptable Objects» (Game Architecture with Scriptable Objects), очень рекомендую с ней ознакомиться.
Другая замечательная особенность в том, что когда вы разберетесь со Scriptable Objects, то, скорее всего, не захотите больше использовать другие форматы сохранения данных, такие как JSON или XML, поскольку SO — это самый удобный формат для хранения данных в Unity.
Что ж, давайте посмотрим на Scriptable Objects в деле.
Мы написали класс с именем
Атрибут


Создадим папку с названием

Теперь напишем другой скрипт под названием
Добавим в него метод, который будет выводить информацию в консоль. Также запустим проверку, чтобы не выходить за пределы массива, а обходить массив по кругу.
Я назначу вызов нашего метода на клавишу «Пробел». В Unity это сделать очень легко. Благодаря классу
Пришло время переключиться обратно на редактор Unity. Мы наполним наш массив

Теперь давайте запустим проект и протестируем его.

Работает! А сейчас я хочу показать вам, что Scriptable Object может хранить не только данные, но и методы для работы с ними. Например, давайте добавим метод для вычисления цены в класс
Затем используем наш новый метод в классе
Теперь воспроизведем все и посмотрим на результат.

Примеры из этого урока есть на GitHub!
Первая часть рассказа подошла к концу. В следующей статье мы поговорим об использовании MVC в Unity. Но, поскольку мы уже знакомы со Scriptable Objects, добавим несколько новых фишек, чтобы сделать все круче и сложнее, как поступают настоящие гуру Unity.

Добро пожаловать в первую часть моего рассказа о реализации MVC в Unity с помощью Scriptable Objects. В этой статье я написал только про основы работы со Scriptable Objects, и в целом текст будет простым и понятным.
Для начала узнаем, что о Scriptable Objects говорят разработчики Unity:
- Это класс, от которого можно отнаследоваться, чтобы создать объект, который не должен быть прикреплен к другому объекту в сцене.
- Наибольшая польза от такого созданного объекта будет, если применять его только для сохранения данных.
Теперь логично спросить: почему именно Scriptable Objects?
Scriptable Objects — это часть функционала движка Unity, поэтому такие объекты имеют много встроенных возможностей для работы с редактором.
Мне нравится подход, используемый при разработке проектов на Unity. Вы можете создавать собственные инструменты и легко настраивать те, которые установлены по умолчанию. Scriptable Objects заметно расширяют ваши возможности, поскольку позволяют делать пользовательские контейнеры для данных и хранить их как ассеты в проекте.

Изображение выше — это пример использования Scriptable Object в Unity. Один файл .asset, созданный в проекте, может содержать информацию, необходимую для работы нескольких систем, и обеспечивать сохранение их настроек. Если хотите узнать больше, на YouTube есть отличное видео с презентацией про SO (Scriptable Object) под названием «Свержение тирании MonoBehaviour в выдающейся революции Scriptable Object» (Overthrowing the MonoBehaviour Tyranny in a Glorious Scriptable Object Revolution).

Еще один отличный пример показан выше. Здесь игровые объекты ссылаются на объект инвентаря (Inventory), а система сохранения (Save System) управляет ими всеми. Это изображение из другой прекрасной лекции «Архитектура игры со Scriptable Objects» (Game Architecture with Scriptable Objects), очень рекомендую с ней ознакомиться.
Другая замечательная особенность в том, что когда вы разберетесь со Scriptable Objects, то, скорее всего, не захотите больше использовать другие форматы сохранения данных, такие как JSON или XML, поскольку SO — это самый удобный формат для хранения данных в Unity.
Что ж, давайте посмотрим на Scriptable Objects в деле.
using UnityEngine; public class ItemData : ScriptableObject { public string itemName; public ItemType type; public float attack; } public enum ItemType { Dagger, Axe, Sword, Staff }
Мы написали класс с именем
ItemData и несколько свойств, типичных для RPG-игр. Далее создадим несколько таких предметов в проекте, получим к ним доступ из скрипта и выведем значения в консоль. Но сначала стоит добавить одну важную строчку в наш код.using UnityEngine; [CreateAssetMenu] public class ItemData : ScriptableObject { public string itemName; public ItemType type; public float attack; } public enum ItemType { Dagger, Axe, Sword, Staff }
Атрибут
CreateAssetMenu, который мы добавили перед классом ItemData, указывает Unity, что мы хотим создавать файлы .asset, в которых будет храниться наш класс, через меню. Иначе мы не сможем делать это с помощью правой кнопки мыши или кнопки Create в проектной папке.

Создадим папку с названием
Items и попробуем создать объект ItemData в этой папке.
Теперь напишем другой скрипт под названием
Inventory, чтобы работать с файлом данных.using UnityEngine; public class Inventory : MonoBehaviour { public ItemData[] inventory; }
Добавим в него метод, который будет выводить информацию в консоль. Также запустим проверку, чтобы не выходить за пределы массива, а обходить массив по кругу.
using UnityEngine; public class Inventory : MonoBehaviour { public ItemData[] inventory; int index = 0; public void NextItemInfo() { if (index > inventory.Length) { index = 0; } Debug.Log("Item name: " + inventory[index].name); Debug.Log ("Attack power: " + inventory[index].attack); switch(inventory[index].type) { case ItemType.Axe: Debug.Log("Item type: Axe"); break; case ItemType.Dagger: Debug.Log("Item type: Dagger"); break; case ItemType.Staff: Debug.Log("Item type: Staff"); break; case ItemType.Sword: Debug.Log("Item type: Sword"); break; } index ++; } }
Я назначу вызов нашего метода на клавишу «Пробел». В Unity это сделать очень легко. Благодаря классу
Input мы можем проверить в методе Update, была ли нажата требуемая клавиша.using UnityEngine; public class Inventory : MonoBehaviour { public ItemData[] inventory; int index = 0; private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { NextItemInfo(); } } public void NextItemInfo() { if (index > inventory.Length) { index = 0; } Debug.Log("Item name: " + inventory[index].name); Debug.Log ("Attack power: " + inventory[index].attack); switch(inventory[index].type) { case ItemType.Axe: Debug.Log("Item type: Axe"); break; case ItemType.Dagger: Debug.Log("Item type: Dagger"); break; case ItemType.Staff: Debug.Log("Item type: Staff"); break; case ItemType.Sword: Debug.Log("Item type: Sword"); break; } index ++; } }
Пришло время переключиться обратно на редактор Unity. Мы наполним наш массив
inventory ранее созданными файлами ItemData из папки Items. Но сперва создадим пустой объект в сцене и добавим на него наш скрипт Inventory.
Теперь давайте запустим проект и протестируем его.

Работает! А сейчас я хочу показать вам, что Scriptable Object может хранить не только данные, но и методы для работы с ними. Например, давайте добавим метод для вычисления цены в класс
ItemData. Чтобы узнать более подробную информацию об этом, загляните в документы здесь и здесь.using UnityEngine; [CreateAssetMenu] public class ItemData : ScriptableObject { public string itemName; public ItemType type; public float attack; public float GetPrice() { return attack * 40; } }
Затем используем наш новый метод в классе
Inventory.using UnityEngine; public class Inventory : MonoBehaviour { public ItemData[] inventory; int index = 0; private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { NextItemInfo(); } } public void NextItemInfo() { if (index == inventory.Length) { index = 0; } Debug.Log("Item name: " + inventory[index].name); Debug.Log ("Attack power: " + inventory[index].attack); switch(inventory[index].type) { case ItemType.Axe: Debug.Log("Item type: Axe"); break; case ItemType.Dagger: Debug.Log("Item type: Dagger"); break; case ItemType.Staff: Debug.Log("Item type: Staff"); break; case ItemType.Sword: Debug.Log("Item type: Sword"); break; } Debug.Log("Item price: " + inventory[index].GetPrice()); index ++; } }
Теперь воспроизведем все и посмотрим на результат.

Примеры из этого урока есть на GitHub!
Первая часть рассказа подошла к концу. В следующей статье мы поговорим об использовании MVC в Unity. Но, поскольку мы уже знакомы со Scriptable Objects, добавим несколько новых фишек, чтобы сделать все круче и сложнее, как поступают настоящие гуру Unity.
