Suppose I have some interface IMyInterface with two or more implementations. Every implementation has different fields, properties, etc., but they all aim to do the same task. All implementations are Serializable.
I’d like to use an implementation of IMyInterface in one of my MonoBehaviours, but I want the user to choose which one to use (perhaps using a dropdown Popup?).
Based on the user’s choiche, I’d like to display the editor for the chosen implementation, so that the user can change its settings.
I’m not sure what you mean by “All implementations are Serializable”. Interfaces can’t be serialized as they are only a “method-contract”. An interface doesn’t contain any data. Furthermore Unity’s serialization system can’t serialize references of an interface type, only types which are derived from UnityEngine.Object. That means user created types are restricted to either MonoBehaviour or ScriptableObject derived types.
So you would need a public variable of type MonoBehaviour or a derived type so it will be serialized and will show up in the inspector. Even though you could write a custom PropertyDrawer and use EditorGUI.ObjectField, it wouldn’t help because ObjectField doesn’t work with an interface type as type restriction. I’m actually a bit disappointed that it doesn’t work. I thought that might be a nice solution, but no. You can use your interface type as restriction, but as result the field won’t accept any reference. Also the ObjectPicker (which shows when you click that little icon on the right side) doesn’t show any matching assets.
The only two workarounds would be to either use the ordinary ObjectField so the user can select any MonoBehaviour derived instance and then manually check for the interface type and if the selected object doesn’t implement it, set the reference to null. The only other solution is to create your own “ObjectField control”. It’s not that hard but still a lot work depending on what features you want. Presenting a dropdown with all instances in the scene would be a way, but if there are many objects this is not a good solution. Providing simple drag&drop support is probably the best way.
In the end you have to ask yourself if it’s worth the all hassle. A solution that should work is to use an abstract base class that is derived from MonoBehaviour. However that of course restricts you to “one” base class. If you use an abstract base class you don’t need to do anything. Just declare a public variable of your base class and you can only select instances which are derived from that base class.