This is because of unity not being able to serialize interfaces, but I need at least the option to add both MonoBehaviour’s and ScriptableObject’s to an array without doing custom serialization.
currently doing something like this:
public abstract class Modifier : MonoBehaviour {}
// public abstract class Modifier : ScriptableObject {} //TODO: find a way to support this
public Modifier[] Modifiers;
usually you just do this but well no interface support
public interface IModifier {}
public IModifier[] Modifiers;
Well they both derive from UnityEngine.Object, so you can try that. Unity will allow you to drag ANY Object into it (Texture, Sprite, etc) but in the code you can reject unwanted objects by casting the thing to IModifier before using it.
You don’t really need to filter them in the inspector, you can just do it at runtime when you actually iterate through the list. I guess it depends on how editor-friendly you want it to be.
The best available thing is to use an Object field with a custom attribute that filters for specific interfaces. It’d be nice to have a cleaner solution, but that doesn’t exist out of the box.
Right, there’s no cleaner solution since the least common ancestor of MonoBehaviour and ScriptableObject is UnityEngine.Object. So there’s nothing in between.
Though afaik Unity does now support serializing interfaces when you use the SerializeReference attribute on the field. Though I’m not sure if you get editor support out-of-the-box or if you have to write your own property drawer.
The PropertyDrawer is no issue for me since I use Odin in my project (editor only mode since it would come with interface serialization support). However there was some issue with SerializeReference that makes it not work as you’d expect (currently don’t remember the exact issue, just that it didn’t work)
Edit: Oh yea this was it: “Fields with [SerializeReference] cannot serialize objects that derive from Unity.Object”
Yes, you’re right. SerializeReference only supports pure managed types^^. I’ve forgot this. In that case you’re stuck at a UnityEngine.Object field with some editor magic around it. Note that you can of course use a property and a hidden cache to actually cast to the interface type after loading. That way you get decent runtime speed and you’re still be able to assign both kind of objects.