BP Interface vs Custom Events

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!

6 Likes