I know how to use interfaces but i dont use them since I can make custom events and communicate between blueprints through references. As far as i know, you need a reference to communicate across blueprints with an interface too, so whats the point of using an interface over a custom event and visa versa?
From a design perspective, interfaces can be used to execute events on objects where you don’t know what the class is. It also allows multiple different classes to execute the same events.
So if you have a bunch of interactive objects in your scene, you can have an interface with a function called “Interact”. When your player presses a button, it sends a message to “Interact” with any object it overlaps with or whatever the line trace hits, for example. This way your player object doesn’t have to know if it’s overlapping a lamp to turn off or a dog to pet, it simply sends a message to an object and the object executes its own logic.
Doing this with references would require you to have a base class, for example AInteractible, with the “Interact” function that each inheriting class overrides. But not only would all of these objects need to inherit from AInteractible, your player also has to load the AInteractible class in order to execute the “Interact” function on one of these objects.
That leads us to the technical consideration. A cast or reference requires your script to load the class of object you’re referencing or casting to. Usually this is not an issue, but for large classes with lots of data this can eat up a bunch of memory, especially if you have multiple instances of player characters all interacting with AInteractible actors at any given time. This memory will be reclaimed by garbage collection after enough time passes without loading it again, but it’s something to consider. An interface on the other hand is very lightweight as it only contains function headers and some meta data, no variables or logic. You can load dozens to hundreds of interfaces at once for the same price of loading a single mega-class. When sending an interface message you’re only loading the interface class instead of the full class of the reference or cast.
Now for the cons - it does take longer to send interface messages than it takes to execute an event from a cast or reference. The difference is mostly imperceptible, but with enough ‘simultaneous’ executions you may notice a difference. The other consideration is design time - setting up an interface override and message is kinda clunky. I still don’t like doing it. But it’s a necessary evil for larger games.
For perspective, my game took about 49 seconds to load because my player controller and pawn were full of references to other objects. At first it wasn’t a problem, but a year into my project the startup time was too much to ignore. I went through and removed references, replacing direct calls with interface calls. My load time is now about 11 seconds. All because my controller and pawn aren’t loading the UI and powerups and interactible objects all at once.
But doing that wasn’t trivial. It took me about two days. Two frustrating days hunting down the hard references and creating interface replacements. Had I designed for interfaces to begin with, I could have avoided the extra time investment. I would very much recommend making the switch as early as possible unless your game will be limited in scope so as not to have more than a handful of light classes if you plan to load all into memory at once.
iTween : Free, smooth, procedural object animation
easyCSV : Read data from any CSV and put them in an easy-to-access string map!
Runtime DataTable : Import and export game data to and from CSV or Google Sheets while your game is running!
Using an Interface, you don’t need to do Cast to, when you do Cast to, you will import all the things from other actor, like Meshes, Textures, Sounds… It`s not good for large projects, increases the loading time and decreases performance.
What you explain is a bit confusing for me.
When you cast, it is from an object that is already loaded into memory, so it is generally asked if it is valid.
Are you saying that with the interfaces you do some kind of magic and you don’t need to have the classes loaded in the game? Can you talk to the HUD without creating the widget?
If you have many references in the player and in the controller, you should think of another way of doing things.
I use event dispacher to get it super clean from cross referencing.
Also to mitigate the initial load, I have functions on demand that are only loaded into the game when it has to be used for the first time, or returns the object already loaded and cast
One thing not mentioned here is that Custom Events don’t have returns while interface function calls can have the target chew on data and spit it out, since they are functions.
I know how to use interfaces but i dont use them since I can make custom events and communicate between blueprints through references.
Imagine line tracing through an open world hitting actors, the trace sweeps over grass, trees, rocks, fish, clouds, collision volumes, people and what not. Unless everything inherits from some mega class, you’d need to:
And you will not store a hard reference to everything. Direct comms, interfaces and dispatchers are all situational and you will need them all eventually, depending on the scope.
- if I nest a user widget inside another widget and need the child to communicate with the parent, I’d dispatch it and have the parent listen:
No real need for interface call here, custom event or another hard reference. You choose the right tool for the job.
yes, I really believe that this is the true sense of the interfaces, avoid multicast to do the same to completely different objects.
Question Then. So often I see a cast to another blueprint on begin play. Then that is saved to a variable. You then use that variable to reference the casted-to blueprint and all of its varables easily. Using that variable reference to access the other blueprint is no better than casting each time - is that correct?
So at what point does casting become not such a good idea? As in how big/complex of a blueprint should you not cast to?
Using the variable you don’t need to do the casting every time so that’s one way to optimize. The variable does not occupy much because it only contains the reference, not the object itself.
Although the casting is not very newsworthy it is always better to save it if you use it a lot.
To use it a couple of times, it is not necessary to save it in a variable either.
Good work! The tools exist because not every tool is suited to every job. Sometimes interfaces aren’t the way to go!
But one thing to keep in mind - if your BP has any casts anywhere it will load the classes in each cast when the BP loads. Always. Whether your code hits that node or not doesn’t matter, that’s just the way BPs work.
Casts aren’t always evil, especially if the object you’re casting to already exists in memory. For example, your player character exists all the time, so it’s not an issue to cast to your player character from a collectible object. The game doesn’t need to load the same object multiple times. It may not have the class of the collectible loaded though. So it’s best not to cast to the collectible from your character class. If you do, it will load the collectible class when the player character’s class loads.
The thing is, when you overlap with a collectible object, your player character knows it overlapped with an object in the world, not specifically a collectible. It doesn’t have to load the collectible class. It only references the base AActor class which is already in memory anyway. It doesn’t have to worry about any functions or variables in the collectible class. But if you cast to the collectible, it has to already know about the class when the player is loaded. With an interface, you’re sending a message to an actor and the receiver, if it implements the interface, knows what to do from there. No extra memory overhead.
So casting isn’t inherently bad, see the post above for examples of when it’s a non-issue. And sometimes it’s not really avoidable, like creating a widget. You have to load the class in order to instantiate it, so you may as well save the reference.
Saving a reference and casting to a class have the same load overhead. In that case it doesn’t matter which you choose. However it does take CPU time to cast to something even if it’s loaded into memory, so if you must cast it makes the most sense to cast once and save the reference. A pointer to another object doesn’t take up much memory after the initial load, so go nuts. But do try to avoid casts if possible. Interfaces are great for this.
Casting in Blueprint or getting a Variable are both function calls and thereforce have pratically the same overhead so don’t bother picking one over the other but pick whatever is convient.