Изменение переменных в скрипте меняет переменные в ScriptableObject

Создаю игру на Unity. Храню стартовые характеристики персонажей в ScriptableObject. В начале игровой сессии я присваиваю значения SO локальным переменным скрита. Однако при изменении этих локальных переменных почему то меняются и исходные значения в SO, хотя напрямую я их не трогаю.

public interface ICharacterValues
{
    public float speed { get; set; }
    public float speedMultiplier { get; set; } 
    StartValuesSet();       
}

public class CharacterSO : ScriptableObject
{
    public float speed;
    public float speedMultiplier;
}

public class CharacterValues : MonoBehaviour, ICharacterValues
{
    [SerializeField] private CharacterSO _characterSO;
    public float speed { get; set; }
    public float speedMultiplier { get; set; }

    private void OnEnable()
    {
        StartValuesSet();
    }

    public void StartValuesSet()
    {
        speed = _characterSO.speed;
        speedMultiplier = _characterSO.speedMultiplier;
    }

    public void SpeedUpgade()
    {
        speed *= speedMultiplier ;
    }
}

При этом, после изменения параметра speed из скрипта меняется и также и speed из SO из-за чего после выхода из плеймода значения там уже не те что нужны


Ответы (1 шт):

Автор решения: Yaroslav

Если значения меняются, значит где-то есть операция присвоения, но не в том коде, что ты тут написал. Её можно легко найти, посмотрев ссылки на соответствующее поле.

Но причина ошибки в первую очередь из-за нарушения инкапсуляции! Вот как выглядит код, дающий гарантии, где присвоения нет и быть не может, исключительно модель данных для чтения:

public class UnitProfile : ScriptableObject
{
    [SerializeField] private string _name;
    [SerializeField] private float[] _baseStats;

    public string Name => _name;
    public IEnumerable<float> BaseStats => _baseStats;
}

Очень хорошей идеей является использовать ScriptableObject для профилей юнитов, где в частности указаны базовые статы. Но как-то странно плодить SO для каждого значения, работать с этим, это какой-то суровый челендж.

IСharacterValues это абстракция, но почему-то в нём поля с вполне конкретным именем. Модификаторы public там кстати не нужны, интерфейс сам по себе контракт для внешнего пользователя, поэтому там и так всё public. И не очень понятно для чего этот интерфейс тут нужен... словно есть некие Сharacter, но без неких Values и отличить одних от других, можно с помощью этого интерфейса.

Тебе стоит посмотреть варианты, как люди реализовывают StatSystem, например этот вариант.

→ Ссылка