Корректно ли писать логику в scriptableObject?
У меня есть префаб корабля, который имеет характеристики и логику. По своей неопытности при создании этого объекта я сделал обычный спаун. Т.е у каждого спаунящегося объекта были cвои характеристики и прочее, что, конечно, грузило систему. Затем я узнал о scriptableObject, но, как понял, логика там не пишется. Там следует прописывать только описание объекта. Но в курсе Р. Сакутина логика пишется в SO. Вопрос: Корректно ли писать логику в SO и будет ли она вообще в таком случае выполняться?
Ответы (3 шт):
По идее, ScriptableObject создан для хранения информации, настроек, конфигурации. Если в классе-наследнике от ScriptableObject будет реализована логика - то она будет работать. Но зачем нагружать класс предназначенный для хранения информации какой-то бизнес-логикой?
При проектировании лучше все-таки писать классы таким образом, что бы их поведение было предсказуемым, ожидаемым. Вы, к примеру, стали бы ожидать, что книга с описанием технических характеристик корабля сама управляла бы кораблем или командовала экипажем? Но, при этом, вполне ожидаемо было бы, если такая ТТХ-книга могла выдавать какие-нибудь расчеты, вычисления, связанные с хранимыми в ней параметрами.
На логику в ScriptableObject каждый может иметь свою точку зрения. Это холиварный вопрос. Но я бы советовал отделить эту логику.
Чаще всего ими пользуются как контейнером данных, набором однотипных профилей с разными настройками, контейнером с массивом таких профилей или константами. Конечно в таких ScriptableObject могут быть методы для получения данных в другом виде, более удобным образом по enum или ключу, получение рандомного из некого массива, сгенерированных данных на основе настроенных параметров и тд.
Он может даже иметь сущность отвечающую за то какие элементы массива разблокированы для использования и какой текущий и сущность сохранения и загрузки этих данных, как например для набора скинов.
Очень удобно использовать его даже без всяких полей, как общую точку доступа вне сцены вместо статических сиглтонов. Если объект не привязан к конкретной сцене, то можно сделать его ScriptableObject, вот и весь принцип.
ScriptableObject конечно не исполняет магические методы Unity: Start, OnEnable, Update и тд. Если он больше чем контейнер данных, кто-то должен его разок пнуть при старте игры, что бы он проинициализировался/загрузил данные и тд. Некая "точка входа".
У Ромы большой опыт, больше чем у тех, к кому можно обратиться с вопросом на формух в интернетах.
Писать логику в ScriptableObject очень даже корректно. Но нужно учесть, что в отличии от MonoBehaviour, тут не будет событий вроде Awake(), Start() и прочее.
Например можно подойти к коду в ScriptableObject следующим образом:
Описать интерфейс, шаг опциональный но поможет понять идею:
public interface ISomeSubSystemManager { void Init(); void DoTheWork(); void ProcessSomething(); }Сделать базовый SO на основе этого интерфейса:
using UnityEngine; // We don't want create 'CreateAssetMenu' items, because its our base class public abstract class DamageSystemManager : ScriptableObject, ISomeSubSystemManager { public List<Unit> units { get;set; } public abstract void Init(); public abstract void DoTheWork(); public abstract void ProcessSomething(); public abstract void AddUnit(Unit unit); }Описываем логику систем(ы):
using UnityEngine; [CreateAssetMenu(fileName = "GroundUnitsDamageSystemManager", menuName = "DamageSystemManagers/GroundUnitsDamageSystemManager", order = 1)] public class GroundUnitsDamageSystemManager : DamageSystemManager { public override void Init() { // Init something } public override void DoTheWork() { // Do some work } public override void ProcessSomething() { // Process Something } public override void AddUnit(Unit unit); { // Add and Process new units } }Уже из основного кода можно работать с созданным(и) экземпляром(и) этих SO:
using UnityEngine; public class SomeMonoBehaviour : MonoBehaviour { public DamageSystemManager damageSystemManager; void Start() { damageSystemManager.Init(); } void Update() { damageSystemManager.ProcessSomething(); } }
Для описанной выше системы, обычные классы могут быть более пригодны, но я хотел описать, на что можно расcчитывать, если юзать SO как контейнер с кодом.