Skip to content

Instantly share code, notes, and snippets.

@xealgo
Last active February 17, 2024 23:33
Show Gist options
  • Save xealgo/411da4f291ce55804cd122e6c821fc12 to your computer and use it in GitHub Desktop.
Save xealgo/411da4f291ce55804cd122e6c821fc12 to your computer and use it in GitHub Desktop.
Unity add custom data types to list in inspector

Motivation

I wanted the ability add custom types to a list on a scriptable object asset within the inspector. These types extend a common base and are standard C# classes. Normally Unity doesn't know about your standard C# classes unless you create a reference for each type or create some complex custom editor solution. Manually adding the types to the list will result in a Type Mismatch within the inspector. There are all sorts of use cases for this such as custom properties, creating an editor friendly strategy pattern system, etc. However, not being able to edit the fields is a real pain in the ass.

Fortunately unity provides two super useful attributes: [SerializeReference] and [ContextMenu].

Example:

interface IMyDataType {}

[System.Serializable]
class MyCustomType : IMyDataType {
  public int x;
}

[System.Serializable]
class MyOtherCustomType : IMyDataType {
  public string name;
}

class MyCoolSo : ScriptableObject {
  [SerializeReference] protected List<IMyDataType> customTypes;
  
  [ContextMenu("Add Custom Type")]
  public void AddCustomType() {
    MyCustomType type = new();
    customTypes.Add(type);
  }
  
  [ContextMenu("Add Other Custom Type")]
  public void AddOtherCustomType() {
    MyOtherCustomType type = new();
    customTypes.Add(type);
  }
}

Now like magic, you can open the inspectors context menu, click on "Add Custom Type" and boom! Your custom type will be added to the custom types list and editable within the inspector. I was worried that it wouldn't persist when restarting the editor, but awesomely enough, my types and values were still there just as I left them.

The next step would be to figure out how to decouple the factory methods from the class. It's fine with 2 or 3, but 20, 30 would create a lot of noise. In addition to this, I went a step further. Each custom type has an SO reference. This way I can reuse the same SO asset for every object that needs it, but have the ability to set custom values without needing 50 copies of the same SO.

The example code is very simplified and doesn't reflect the best practices, but the take away here is the use of [SerializeReference] allows you to easily add custom types to a list within the editor while making their attributes editable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment