2

Say I have a ScriptableObject Item:

public class Item : ScriptableObject
{
    public new string name;
    public string description;
    public Sprite sprite;
}

The only issue is that the fields can be modified:

Item item = new Item();
item.description = "Overwrite";

I want them to be readonly. I found this workaround using properties:

public class Item : ScriptableObject
{
    [SerializeField] private new string name;
    [SerializeField] private string description;
    [SerializeField] private Sprite sprite;

    public string Name => name;
    public string Description => description;
    public Sprite Sprite => sprite;
}

The only issue is that this effectively doubles the length of all of my ScriptableObjects and seems cumbersome. Is there another preferred way to make ScriptableObject fields readonly without the extra code and still serializing fields?

Isaac Thompson
  • 75
  • 1
  • 1
  • 7

3 Answers3

2

You can use Field-Targeted Attributes:

public class Item : ScriptableObject{
    [field: SerializeField] public string Name { get; private set; }
    [field: SerializeField] public string Description { get; private set; }
    [field: SerializeField] public Sprite Sprite { get; private set; }
}
Lyrca
  • 528
  • 2
  • 15
0

Don't directly use the original scriptable object, use its runtime copy to prevent the original value from being modified.

You can do it by using ScriptableObject.Instantiate(your_so)

yingdi fu
  • 1
  • 1
-1

You can initialize the fields as properties directly and add the get method to it. set method is by default set to private set;. It restricts any external modifications of the properties. These properties can be set privately, i.e. they are accessible and modifiable within the script.

public string Name { get; }
public string Description { get; }
public Sprite SpriteObj { get; }

Note: Naming convention of properties is that they start with an uppercase letter. Changing the property name to SpriteObj so that it doesn't clash with the inbuilt component name.

Geeky Quentin
  • 2,469
  • 2
  • 7
  • 28
  • Your implementation is incorrect, this would strip OP's ability to modify the field in the inspector since you aren't including `[field: SerializeField]`. Also, naming conventions vary from person to person and studio to studio. So it's best not to project yours onto others. Even if OP had written Sprite Sprite it would be perfectly valid. The compiler knows the difference. – arkon Feb 18 '23 at 20:36