The main problem I am trying to solve is to decuple my system and have the ability to swap implementations in the editor without touching code.
So I would like to know what people use to assign interfaces in the editor or maybe you have your own view on the problem and solve it completely in a different way?
Down below my summary of options which I found here and online.
Option 1
Is to use SerializeReference + CustomDrawer to select concrete type
Example of this is here GitHub - mackysoft/Unity-SerializeReferenceExtensions: Provide popup to specify the type of the field serialized by the [SerializeReference] attribute in the inspector.
This is a great tool but the downside of this is that you can’t assign objects derived from Unity.Object which is a limitation of SerializeReference.
Option 2
Create concrete types derived from Unity.Object and then restrict it by your interface in the drawer
Example: GitHub - Cippman/Unity-InterfaceReference: A serializable class that holds the reference to an interface
Option 3
Use AbstractClasses this is not the same obviously but I think a huge plus of this is that it just works without packages extra drawers and stuff.
Note that you can always wrap your plain class in a UnityObject or have a plain Class with reference to Unityobject which will pass through calls as a workaround for these workarounds
So my questions are what do you use if anything? And what are your reasons? Am I missing something?
In a normal development environment, we inject interfaces through the constructor this way we swap the implementation without touching the code. In unity, my way to go is (normally) to use SO as “interfaces” and the editor as an injector, then the component injects themself into the SO, this way I can change the behavior in the editor without touching the code. The downside for me is that data must be public to allow SO to access it but depending on the case I pass a second parameter to work as a context.
Replying to @Nefisto first, this is my go-to for ctors in Unity:
Factory Pattern in lieu of AddComponent (for timing and dependency correctness):
Regards @aguskos if at all possible I like to have scripts discover other services right on the same GameObject, or on a child, usually with GetComponent(). This only works for items that are hierarchally together in scene, but that’s a lot of stuff.
Otherwise a lazy instantiated scene singleton just seems to solve so many issues: no dragging to do in the editor, yet everybody can just find it by reference and use it.
@Kurt-Dekker If I understood it right you want to inject the interfaces using the Create method right? If this was the case how you allow the designer to customize things? I mean, if you have an interface IDrink and the player has a list of IConsumables, you can insert drinks in this list via the constructor or another API but how can the designer create a potion that heals distinct amounts?
The factory posted above is more for you to make the correct object, give it the right config, such as from a ScriptableObject (that MIGHT come via interface, or concrete).
The designer would be involved in simply creating a palette of these ScriptableObjects that you could load and slot in at your factory time, perhaps supplied by a larger notion of “oh we need to have object Elephant42 now, get the config ScriptableObject for Elephant42 and make me an IAnimal.”