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

[SerializeInterface] I created a tool to Drag and Drop Interfaces in the editor. (Version 0.04)

Discussion in 'Assets and Asset Store' started by TheNullReference, Jul 26, 2023.

  1. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    222
    example.png

    This tool will allow you to use the [SerializeInterface] Attribute to drag and drop MonoBehaviours and ScriptableObjects.

    The inspector will only accept objects that implement the correct interface.

    I made this tool because [SerializeInterface] is a commonly requested features, and something I wanted in order to make code that follows SOLID principles. https://forum.unity.com/threads/serialized-interface-fields.1238785/

    ___

    It uses a Source Generator, hence classes using [SerializeInterface] will need to be made partial. It will only work in versions of Unity that support Source Generators.

    I only finished making this over the last few days and still needs more testing, so please get back to me with any issues you have.

    UPDATE 1:

    - Classes using [SerializeInterface] can now implement ISerializationCallbackReciever
    - Other attributes used alongside [SerializeInterface] will now also be applied to the backing object (i.e. appear in the inspector)

    UPDATE 2:

    Lists!

    Screenshot 2023-08-05 235254.png

    Fixes:
    - No longer attempts to serialize readonly fields.
    - No longer attempts to serialize static fields.
    - No longer attempts to serialize fields that are not interfaces.
    - Attributes that don't belong in the global namespace should now work.

    New:
    - Added support for Lists.
    - Added support for readonly Lists so long as their value is not null.

    UPDATE 3:

    Added support for Generic Interfaces.
     

    Attached Files:

    Last edited: Aug 7, 2023
    mbussidk likes this.
  2. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,104
    This is a very interesting approach to solving the interface conundrum - nice work! :)


    Couple of potential improvement ideas that come to mind:

    1. Attributes added to fields with the SerializeInterface attribute could be also copied over to the generated serialized fields. This way could use things like HideInInspector, Odin's attributes etc. to control how the Object reference control should be drawn.

    2. At the moment it's not possible to use ISerializationCallbackReceiver and the SerializeInterface attribute at the same time. In theory it could be made possible to support this, by having the generated code implement the interface explicitly, and have it also call an implicitly implemented version in the user's code.
    Code (CSharp):
    1. public partial class Example : MonoBehaviour
    2. {
    3.     [SerializeField] private Object example_Object;
    4.  
    5.     void ISerializationCallbackReceiver.OnAfterDeserialize()
    6.     {
    7.         example = example_Object as IExample;
    8.         OnAfterDeserialize();
    9.     }
    10. }
    3. Plain old C# object support would of course be super nice for maximum flexibility... albeit very challenging to implement inspector-wise :confused:
     
  3. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    222
    1) and 2) are really good points and fairly easy to implement.

    3) would be difficult and is probably outside the scope of what this should do. I wanted this feature so that it still 'felt' like I was coding in Unity. If you really wanted that level of flexibility, perhaps just using IoC Container is better.

    In theory [SerializeInterface, SerializeReference, Inject] would still work, so long as injection is called after OnAfterDeserialize.
     
    SisusCo likes this.
  4. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,104
    That makes total sense. It's nice how simple this is at the moment - and having access to both SerializeInterface and SerializeReference already give an enormous amount of flexibility.
     
  5. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    222
    Your 1 and 2 suggestions are great ideas and have been implemented, very quick.
     
    SisusCo likes this.
  6. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    222
    3rd Update.

    Added support for lists.
    Will even serialize read only list so long as they have a value.

    Code (csharp):
    1.  
    2. // Won't Serialize.
    3. private readonly List<IFoo> fooList;
    4. // Will Serialize
    5. private readonly List<IFoo> fooList = new();
    6.  
    Fixed some issues where I wasn't checking if a field was readonly, static or a non interface. Should now only attempt to serialize Interfaces.

    There was also a problem of attributes carrying over if they weren't in the global namespace. Should be fixed now.
     
  7. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    222
    4th Update.

    Added support Generic interfaces.

    Most edge cases should be covered, including nested generics.
     
    VadanaPon likes this.