Hi there guys, thanks for all the help by the way.
I’m right now faced with a design choice and i would like to hear your opinions as to which implementation would be better in the long term.
I have an interface called InteractableInterface which simply put, lets some actor be interactable, it has the StartFocus, EndFocus and Interfact methods. This interface is created via C++, and the actor which can trigger this events is also on C++. So i decided for the sake of being clear, i should implement the interface via C++ (because if i implemented the interface on blueprints, c++ couldn’t cast the actor if it implemented the interface).
My idea was to originally implement this interface on the actor itself creating a InteractableActor which the other actors in the world could inherit from and then override the methods on it for specific implementations. Default method would be to highlight the actor when on focus and stop highlighting when out of focus. The problem is if i ever create another c++ interface, i would have to create another class that could implement the interface, and i would lose some of the composition blueprints give me (being able to add or remove interfaces at actor level).
Then it came to mind the power of components, and how it’s always prefered to use composition vs inheritance. So the other option would be to create different components which implements this interface and attach them to the actor, this component could be HighlightsOnFocusComponent, etc…
For me, the inheritance path looks way clearer, and won’t let multiple components that implmeent the interface be attached to the actor which would be a nightmare to debug.
Also i would have to change the way the events are triggered, because right now i’m looking if the actor implements the interface, but i should look for all the components of the actor who implement the interface.
My question is, maybe there is some clearer way i’m not thinking right now? should i just go with inheritance? or is it prefered to use composition in cases like this??
How is your workflow when programming in c++? when do you program on blueprints if ever and how do you make the c++ interfaces work with blueprints?
greetings!
I want to start off by saying that I am no expert and still pretty newbish.
I feel that interfaces seem best used for situations where different classes need different implementations of the same set of methods without needing to cast to the derived class and components are best used for things where the implementation will be the same for different classes.
I would use inheritance in situations where I have want to make another object that is mostly the same but I just want to adjust a couple of things but it really depends.
I can shed some insight on how I’ve solved this (and a few other) issues when I was implementing this in my own project.
Interfaces can be extremely powerful. I got a component which handles all of my combat system stat tracking and calculations. Since this is accessed REALLY often in many different sections, I’ve create a CombatInterface which my BaseActor implements and it lets me retrieve this component from my BaseActor. This is leaps and bounds ahead of the alternative of not using this interface, as it saves me a ton of “GetComponentsByClass” calls, and consequently, a ton of iteration over my actor’s components.
That is an example of where interfaces shine.
I did not however choose this approach for my ActionComponent (InteractComponent if you will). The main reason being that the component does a ton more than just call a function on the actor. If it were to be a simple ActionInterface, each actor would have to implement all of the functions from the interface. This way I got a bunch of pre-defined actions (Start Dialog, Loot, Read, Open Door) but I also have one GenericAction which calls a FOnGenericAction multicast delegate. Actors needing this would then just bind a function to this delegate (Even more handy, Blueprint actors that need this have a neat “OnGenericAction” event button in the BP editor, much like collision components have “OnBeingOverlap” etc.).
And of course, if this were an interface I’d run into the scenario of e.g. some enemies being interactable (perhaps they become friendly and “talkable” after they drop below 50% health) and some not. This adds an additional layer of complexity that means that you probably won’t be able to implement the interface in the base class but would have to do it per sub-class or even per BP. And making an interface that works in both BP and C++ is a can of worms in and on itself.
Long story short, use interfaces for widespread actions that you can implement in a base class, use components to encapsulate more complex logic.
We are using an interface for the exact same thing:
InteractiveActors (extends Actor)
attachable InteractiveComponents which are either InteractiveStaticMeshComponent (extends StaticMeshComponent) or InteractiveSkeletalMeshComponent (extends SkeletalMeshComponent)
our interface is called IInteractiveBase, and has common interaction functions like MouseOver(), MouseOff(), GetToolTip(), etc…
The interface seems ideal here because:
AFAIK Unreal doesn’t play well with multiple inheritance
these are disparate classes that have some similar functionality but do not have a common parent class
Its working well, so if you have any questions on implementation going the Interface route I could probably help.