I’m trying to use ScriptableObjects to provide an in-Editor configurable item definition; it needs to implement an interface defining the fields the item definition consists of, so the scriptable object can be passed in when an item is created. However, when I define properties on a ScriptableObject, they aren’t shown in the inspector.
public interface IItemType
{
string Name { get; }
}
public class ItemType : ScriptableObject, IItemType
{
// public string Name; // will show in editor, but doesn't satisfy the interface
public string Name { get; set; } // satisfies the interface, but doesn't show up in the editor
}
Marking the property with SerializeField doesn’t help.
So, how do I do this? Is the only way to implement a custom editor for every ScriptableObject type I define that needs to implement this pattern?
accessors do not show up in the editor. unless of course, you make a custom editor for your class. otherwise, only public fields, or private fields with serialize field, show up in the inspector.
As TimmyTheTerrible said, Auto-Implemented Properties ( Microsoft C# Programming Guide) do not show up in the editor. You will have to go the traditional way of using properties, as it is shown in the example here: Using Properties (Microsoft C# Programming Guide).
In another thread here in the forums, someone said that from C# 7 onwards, one can do this using auto-implemented properties:
[field: SerializeField]
public string Name { get; set; }
private string mTest1;
public string Test1 { get => mTest1; }
private string mTest2;
public string Test2 { get => mTest2; set => mTest2 = value; }
[field: SerializeField]
public string Test3 { get; }
[field: SerializeField]
public string Test4 { get; set; }
[SerializeField]
private string mTest5;
public string Test5 { get => mTest5; set => mTest5 = value; }
I assumed the readonly properties wouldn’t work, and they don’t. I’d be happy if Test2 worked, but it doesn’t. Test4 sort of works, but results in a funky auto-generated field name in the editor (“<Test 4>k__Backing Field”). I’m sure that can be improved in the future, but it’s not acceptable as it stands. Test5 does work, except that it’s exposed in the editor as “M Test5” not “Test5”; that’s much better than the Test4 case, though, and I suppose I could work with that.
It’s a shame SerializeField doesn’t have an optional parameter to override the field name in the editor.
Instead of an interface, have you considered using an abstract base class that inherits from ScriptableObject?
public abstract class ItemBase : ScriptableObject
{
public string Name; // a field, not a property
// etc.
}
public class ItemType : ItemBase
{
// etc.
}
Hmm…well, here’s a kind-of-dirty but extremely simple option:
[SerializeField]
private string name;
public string Name { get => name; set => name = value; }
C# allows identifiers to be different only in case, and the default Unity inspector automatically capitalizes the first letter when displaying the name of a serialized field, so the private variable “name” should appear in the inspector as “Name”, exactly matching the property.
Any code you write in this class is stuck with the frustrating fact that “name” and “Name” formally mean different things, but if you keep that implementation for the property then in practice it probably doesn’t matter if programmers get the two confused.