[bug?] Scriptableobject Permanent Class Relation

Greeting! I’m in love with ScriptableObject, especially considering how it makes game architecture very clean and singleton-free. But I came across a bug (maybe?)

I have 3 scripts: a normal class containing data, a ScriptableObject class, and a Monobehavior class

//Class containing data
[System.Serializable]
public class Data
{
    public float variable_x;
    public float variable_y;
}
//ScriptableObject class
using UnityEngine;
[CreateAssetMenu(fileName = "Scriptable", menuName = "Test/Scriptable")]
public class Scriptable : ScriptableObject
{
    public Data scriptableData;
}
//Monobehavior Component Class
using UnityEngine;
public class GameobjectComponent : MonoBehaviour
{
    public Scriptable referenceToScriptableObject;
    public Data componentData;

    public void Start()
    {
        componentData = referenceToScriptableObject.scriptableData;
    }
}
  • As usual, I created an instance of ScriptableObject, then fill the variables in the inspector.
  • Then, I create an empty gameobject and attach the GameobjectComponent monobehavior to it.
  • Still in the component, I drag and drop the ScriptableObject into the inspector Scriptable field.
  • Then I run the game.

The component will get the value of the ScriptableObject class to its own class ONCE in the Start() function. No problem here.

But then, if we modify the ScriptableObject value, the value in the component also change. This also happens when we modify the monobehavior value, the scriptable value also change!

So somehow, both Monobehavior and ScriptableObject now shares the same value even without any Update() function to do so. To my knowledge, the value from scriptable SHOULD only be assigned once in Start() function to monobehavior.

So to undo this problem and break the “connection”, I need to change Start() function, so that it assigns the Data class variables one by one. It’s still assigning value from ScriptableObject once when the game runs, but the connection doesn’t happen.

//Monobehavior Component Class
using UnityEngine;

public class GameobjectComponent : MonoBehaviour
{
    public Scriptable referenceToScriptableObject;

    public Data componentData;

    public void Start()
    {
        componentData.variable_x = referenceToScriptableObject.scriptableData.variable_x;
        componentData.variable_y = referenceToScriptableObject.scriptableData.variable_y;
    }
}

Was this a feature or a bug?

It’s a feature :wink: You are copying the REFERENCE to the class data, the scriptable object and the Gameobject are both pointing to the same place in memory. There is a super simple fix:
Rename “public class Data” to public struct Data". You should do that anyway when you have a class that only contains data, as a struct is not a reference type, but a value type.

1 Like

Thanks for confirming this. In my case, I have a very complicated system that would be better to use a class since the same data structure is used multiple times. Thank you!