Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Make Field accept either MonoBehaviour or ScriptableObject

Discussion in 'Scripting' started by HellGate94, Oct 1, 2021.

  1. HellGate94

    HellGate94

    Joined:
    Sep 21, 2017
    Posts:
    132
    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:

    Code (CSharp):
    1. public abstract class Modifier : MonoBehaviour {}
    2. // public abstract class Modifier : ScriptableObject {} //TODO: find a way to support this
    3.  
    4. public Modifier[] Modifiers;
    usually you just do this but well no interface support

    Code (CSharp):
    1. public interface IModifier {}
    2.  
    3. public IModifier[] Modifiers;
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    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.
     
  3. HellGate94

    HellGate94

    Joined:
    Sep 21, 2017
    Posts:
    132
    this would need a custom inspector to filter just the intended types.
    while it would technically work, I would like to have a cleaner solution.
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    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.
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,195
    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.
     
    Bunny83 likes this.
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,525
    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.
     
  7. HellGate94

    HellGate94

    Joined:
    Sep 21, 2017
    Posts:
    132
    yea that's my conclusion for now as well.

    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"
     
    Last edited: Oct 1, 2021
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,525
    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.