How to cast an object to its interface using Blueprint Scripting?

hi, what are you trying to achieve exactly?

I can’t cast my GameState blueprint to IGameClock (the interface it implements). This is preventing me from passing my GameState object to an “exposed on spawn” class variable of type IGameClock.

Here’s an overview of my blueprints:

  • BP_GameState: My game state blueprint that implements IGameClock.
  • IGameClock: An interface that guarantees public methods for retrieving GameClock information. This is implemented by BP_GameState, it keeps track of a replicated game clock across clients.
  • GameClockHud: A child blueprint of UMG.UserWidget that has one responsibility, display the game clock (Month, Date, Year, Hour, Minute, Second, etc.).
  • MasterHud: A master UMG.UserWidget HUD that has a primitive native widget host on the designer canvas which contains an instance of GameClockHud.

My GameState blueprint (BP_GameState) implements my IGameClock blueprint interface. (See below)

GameClockHud is a child of UMG.UserWidget, this widget’s only responsibility is to display the game clock (Month, Date, Hour, Minute, etc.). On class spawn/construct I want to pass it an instance of my BP_GameState that implements IGameClock, but I would like the variable type to remain as IGameClock. I don’t want the widget to worry about what the concrete object is called, just that it implements IGameClock. (See below)

I attempt to create a new instance of GameClockHud in the MasterHud event graph, but I get compiler errors because UE4 can’t cast BP_GameState to IGameClock (it doesn’t even provide me any nodes to do this).

just an insight. interfaces and dispatchers are only useful if:

  • you want to send one signal to multiple destinations and, on the average case.
  • dont know the reciever (on a dispatcher) or dont know the sender (interface). i might be explaning this way too raw but you can get my point.

on this case, the HUD class (MasterHUD) is creating the widget i asume, that means you get a reference of the clock widget. if i understand correctly, you want the MasterHUD to make “some calculation” and tell the widget to show the result. just call the functions from the reference when you created the widget. IF its the other way, if you want to access the HUD class from the widget, you can still do it without interface. “Get Owning Player”->“Get HUD”->Cast to MasterHUD gives you access to the blueprint.

“IF” you still need/want/areObsessed with implementing interface, you are doing it wrong. you have to click on class Settings on the blueprint that is going to recieve the signal, and down on the settings you add the interface that you are going to use (you have to create it first as i think you already did). Compile the blueprint. and then, on the blueprint that you want to send the signal, you get the reference of the HUD (still need to know where you are sending the signal), and call the Event or Function (Interfaces calls become functions if you add an Output to the call) that you need.

no, that would make it more confusing. the options the default class gives you are from the parent class, thats why you cast, to have access to the child variables/functions.

glad you got your concepts right.

So I figured out the problem.

I was dragging off my GameState variable and expecting to see “Cast to IGameClock” but instead I only saw “Cast to BP_GameState”.

Turns out you need to right click the event graph canvas and search for “Cast to IGameClock” and when it’s added to the canvas you can then plug in the GameState.

A future improvement to UE4 BPs could be to show a list of "Cast to " based off the concrete class and the interfaces it implements.

Turn off Context Sensitive and the Cast_To_IGameClock will appear.

Have Fun =)

2 Likes

Hmm intresting discussion you got going I like to simplyfy things when I think of a Interface.

Think of a Interface like a Contract or Promise. Where you basicly say I dont care if you are a Clock, a Rock a Human I just want you to be able to Fullfill your Contract/Promise you gave me.

Not Inhertance bound, Not type bound just a simple Promise even if its empty and does nothing :stuck_out_tongue_winking_eye:

I think you misunderstood my design/approach I was aiming for.

MasterHUD is given a GameState object which happens to implement IGameClock.

MasterHUD creates a new GameClockHUD widget.

GameClockHUD asks for an IGameClock (on spawn) so it can call the GetMonthAsText() method (as well as the other date time helper methods that return Text objects).

MasterHUD says “I have an IGameClock, let me cast BP_GameState to IGameClock because it implements it”. MasterHUD hands the IGameClock to the GameClockHUD widget.

GameClockHUD received the IGameClock so it calls the IGameClock public methods that return Text objects. This way GameClockHUD is not doing any calculations, it can decide how it wants to display the date time in which every style/layout it wants.

MasterHUD is not doing any game clock calculations either. It just grabs the implementation of IGameClock (BP_GameState) from global namespace. I did not want GameClockHUD to reach into global namespace because that’s programmer hell.

The purpose for an IGameClock interface that BP_GameState implements? I doubt I’m going to leave the GameClock processing in the GameState. My game is in early stages and I know I will find a better place to migrate the game clock calculations. Therefore I don’t want to refactor occurrences of BP_GameState to be IGameClock (or what ever the game clock class name would be).

I’m following S.O.L.I.D principles so I use interfaces to reduce the amount of regression bugs caused by refactoring/changes.

I hope all this made sense :slight_smile:

Exactly. That is why my game state implements IGameClock (for now) and that’s exactly why GameClockHUD wants an IGameClock and not a GameState, or a GameProcessorObject.

GameClockHUD only cares if it’s given IGameClock because the object that implements IGameClock is gauranteed to have Get[Month,Date,Hour,Minute,Second]AsText() functions.

Sure said nothing against it. Its a normal usecase of a Interface =)