Please help me understand BP interfaces, I'm missing something very basic.

Quick breakdown of my current setup (simplified for brevity):

BP_Time
tickTime function, which ++ time every second. Then calls an entry in BPI_Chronology called updateDay.

BPI_Chronology
passes through the appropriate aforementioned variables.

WBP_Interface
Receives updateDay as an event and uses those variables to set the time on the interface.

WBP_Climate
Receives updateDay as an event and uses the time of day to change the temperature.

I plan on expanding this so it will be called in more and more BPs as the project develops.

Now for the bit I’m confused with:
When I’m doing the message portion of the updateDay, in the BP_Time - tickTime function, I apparently have to plug in a target to the message node.
Which means I have to get a reference in BP_Time to WBP_Interface and BP_Climate and plug it in.

I was of the understanding that BPI would be more efficient that casting, but in order to get the reference I’m going to have to cast anyway, aren’t I?

I know I’m missing something, probably something very basic, can anyone help me out please?

Casting has almost no performance impact, it is old myth that casting is slow.
It probably started by more experienced ppl telling less experienced ones “do not cast in loop, cast once and store variable”

What i am doing with most of things:

  • i use middle man setup, for me my favorite middle man is BP_GameMode
  • then i make blueprint function library, call all functions BP_Core_PlayerPawn, BP_Core_TheHUD, etc. so when i need reference i just write “CORE” and get them all
  • now my core functions find correct actor/blueprint and cast to it then return correct class
  • every actor that needs such reference executes CORE function and stores CASTED variable with reference, so no more casting during runtime (only at begin play)
  • my core functions also have “IsValid” check and return boolean “success?”
  • oh and those CORE functions are all blueprint pure.

So no more problems with casting.

About interfaces:

  • they are useful only when you want single code to communicate with different blueprint (C++) classes. So you put interface in all of them like BP_rock BP_Tree BP_Bird , and same interface to all of them, so you cast to interface not all different BP classes
  • for any other setup, its easier to just cast to (with CORE function) then create custom event or function in casted to blueprint, and call that event/function directly
  • or create dispatcher in middle man like BP_GameMode, all victims get its reference from get_CORE_GameMode, store that as variable and assign to dispatcher in GameMode. But this is when middle man talks to many different actors

ps.
also (probably) another reason why cast to is considered “bad”.
when from for eg GameMode (or level bp) you get all actors of class: cast to them all in loop store all references in array. So as long as that array with references exists, all those actors are keept in memory, doing their tick and whatever. Then those actors may get all actors (of different class) and store all those references in array. This code would be allocating all the memory for not used actors. This is really bad. So use middle man blueprint that is always loaded, and store reference to it, instead other way around.

1 Like

You have to specify a target when calling an interface, and then ensure that target also implements that interface event (in your case, BPI_Chronology).

It seems you are confusing interfaces with global events… this is not how they work.

From what it sounds like, you have to get a reference to your WBP_Interface widget and WBP_Climate widget, and then use those as the target for when you are calling BPI_Chronology in BP_Time.

So generally, what you can do is create a BP of class HUD, a container HUD widget that serves as the container for all individual HUD widget elements (WBP_Interface and WBP_Climate), and then use interfaces to communicate from BP_Time → HUD BP → HUD main widget → WBP_Climate

An example:
HUD class creates and adds the main HUD widget to the viewport

HUD class implements an interface event, with target the created HUD widget from above:

In the HUD widget, the same interface event is implemented, but targets the specific widget (in your case, this would be WBP_Climate for example):

Then in your WBP_Climate, you will just implement the BPI_Chronology interface event and perform your logic as desired.

In your BP_Time, you will either have to get a reference to your HUD class, and then call BPI_Chronology on the hud class. There are many different ways of doing this, but a naive approach would be:


Store the HUD has a reference, and then call BPI_Chronology on it. This will then go through the flow outlined in the above images, and should do what you intend on doing:

Interfaces vs. Casting:
Suppose you are making a shooter game, where if the bullet hits an actor (i.e. BP_Enemy), you want to do some logic on that class.

Now, in the bullet class, when the bullet overlaps with something, you could cast to BP_Enemy, and if true, call a custom “OnHit” function / event you have implemented in BP_Enemy.

The problem with this approach is manifold:

  1. This is not scalable… what if you have 1000s of objects that you can hit… and each class has their own bespoke “OnHit” logic? You shouldn’t be branching and casting for every possible instance because in BP_Bullet because:

  2. Whenever you cast, you create a dependency / reference from one class to another. This means that for every bullet shot, it needs to async load all the referenced objects in memory.
    This becomes a problem on larger projects and lower-end devices where memory is limited
    If you’re ever wondering why your editor or game is slow, this is one of the reasons.

What this means in practice is that the bullet will know everything about anything that it can hit, including aspects of the actor that the bullet really doesn’t care much about (i.e. what color the door is that you can shoot, or what sound effect is should play when the bullet shoots the door)

  1. In principle, the bullet really doesn’t need to know what it has shot, it just needs to know that is has shot something, and whatever was shot, will implement the “OnHit” logic.

Instead, if you implement a single “OnHit” interface everytime the bullet overlaps with something, if the overlapped actor implements the OnHit interface event, it will implement that logic.

This makes your architecture more scalable and modular, and reduces memory footprint.

1 Like

Appreciate you taking the time. I don’t think i was understanding the use case very well at all. I appreciate you clearing it up. Thank you.

Wow, that’s a heck of a response, thanks, i think i get it now. appreciate you taking the time.

Let us know how it goes!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.