Download

How to call a Blueprint Custom Event from C++ code?

Hey guys.

I need to know how to call an Event made with Blueprints inside C++ code

I wanna call this event from C++:
Capture.JPG

Here

That says another thing.

I want to be able to call my event (created with Blueprints) inside the C++ code, in this way:



OnPlayerKilled();

I’m not sure if there’s an easy way to call a function that was created in blueprints via C++ but I handle this by creating a BlueprintImplementableEvent in a base class in C++ that the blueprint uses as it’s parent and then use it just like in your screenshot. Then in C++ or blueprints I can call that event anywhere I want.

This is the approach I use too and it has worked well for a project with a heavy mix of both C++ and BP.

Plan your class hierarchy ahead. Any time you create a new blueprint ask yourself whether you’ll need to be accessing a part of it from C++ (if your project uses both C++ and BP, chances are the answer is always yes). Start with a base class in C++ like Heoki suggested with all base properties and functions in place. If necessary use BlueprintNativeEvent instead of BlueprintImplementableEvent as well - there are cases where only some BPs will need to override(/implement) the function behavior so having a base implementation in C++ with BlueprintNativeEvent may be useful.

The most complex form of this I’ve seen is when you start with interfaces defined in C++ that first need to be implemented across a hierarchy of C++ classes and then finally in a child Blueprint at the end of the hierarchy which may or may not want to override the function’s behavior. For this situation there are some pitfalls and syntactical issues you’ll run into but there are some good wiki pages already out there that cover this situation in detail.

Guys, I still can’t understand how to reach that point.

For every HUD I create I use Blueprints because it’s kinda complicate to achieve in C++.

So, please read this Make Widget disappear after x seconds - UE4 AnswerHub

I can’t understand how to solve this problem!

Are “Get Last Player Killed” and the player death event both handled in C++?

If yes, what’s optimal is to have a C++ base class for the HUD. It’s not (all that) complicated - Create a simple C++ class inheriting from UUserWidget and create a UFUNCTION returning FText (you will later bind your variable GetPlayerKilledMessage to this function from the blueprint).

Then reparent your current UMG blueprint to extend from that C++ class (from the class settings panel). This way you can manipulate the text message from within C++ itself. The only other step you’ll need is to create the widget from C++ instead of BP by calling the following:



//Call this from your C++ player controller class when the  game begins:
YourBaseHUD = CreateWidget<UYourBaseHUD>(this, YourBlueprintHUDClass);
if (!YourBaseHUD->GetIsVisible())
      YourBaseHUD->AddToViewport();


In that code snippet, YourBlueprintHUDClass needs to be your actual HUD blueprint so to pass it to C++ create a public variable of TSubclassOf<UUserWidget>in your player controller and from the Unreal Editor you can point that variable to you blueprint HUD (for this method to work your player controller also needs to have a C++ base class and a blueprint subclass from which you’ll set the YourBlueprintHUDClass variable).

Another option is to wrap your Show/Hide timer in a “Do Once” blueprint node. But you’ll still need a way to reset the “Do Once” node the second time the message needs to appear so if you really want to avoid the C++ HUD you’ll have to check for a boolean in Event Tick that will tell you when to process the show message logic and that boolean needs to be set in a class that is easily accessible to your HUD blueprint - you can use the player controller or the player character class for this. Both should be readily accessible from the HUD (via GetPlayerCharacter/GetPlayerController nodes) and with an appropriate cast you’ll have your controller/character’s instance.

But like the answer hub commenter told you - I wouldn’t use event tick for this. You should propagate your event to the HUD class instead of spending every single tick checking for a text variable or a boolean.

Thanks for the answer and the patience.

But when I create a Widget (HUD) in C++, then I can’t open the Graph tab and edit the HUD display

This is the C++ class and I create a Child BP from it

But I can’t see the Graph button

Is the Designer tab not visible on that blueprint?

PS: I edited my previous message with more detail, so check that out as well.

My game uses a similar pattern with base HUD in C++ so this should work. In my case I don’t have a need to make a message disappear after 3 seconds but even that should be possible by manipulating the FText you return from C++ to return a blank string after 3 seconds.

I just thought of one more option as well - whatever events are happening in C++ right now, have those classes propagate the events to their blueprint subclasses. From Blueprint you should be able to easily get a reference to your Blueprint HUD and then you can “push data” onto it or call the “Show/Hide” event directly from the other blueprint.

You may be interested in creating an Event Dispatcher from C++. (Called Delegates) In your Blueprint, you bind your event to the delegate. This way, when you broadcast your delegate, it should fire in Blueprint and in turn fire the bound event. This way C++ doesn’t need to know your Blueprint code in advance but still fire it successfully.

Even for the simplest things, there’s no documentation for C++… disappointed.

I have this:

Then I create these two variables (PlayerCharacter.h)

I call the CreateWidget<>() function (PlayerCharacter.cpp)

And eventually i get these errors:

CreateWidget takes in a PlayerController instance (via “this”) - you seem to be passing a PlayerCharacter so it couldn’t find a matching overload.

BTW Denny’s suggestion is wise - create an event dispatcher in your playercontroller/playercharacter and bind an event from your HUD BP to that dispatcher, broadcast whenever the HUG message needs to change. This way you can skip the C++ HUD stuff like you wanted to as well.

Admittedly I haven’t used event dispatchers as much as I should have, but I think you should be able to easily bind to a dispatcher in your PC right from the HUD itself.

how do I create a delegate of the OnPlayerKilled event in my PlayerCharacter BP? And above all, how do I call it from PlayerCharacter C++ class?

Yes I’m using this on the PlayerCharacter. So I should get the player controller from that player character, how?

GetWorld()->GetFirstPlayerController() works for single player games (there’s some caveat in using that for multiplayer IIRC but I don’t have experience with that scenario).

My game is actually going to be a Multiplayer FPS game.

So I’d like to know if there’s a way to get the controller of this character

I second (third) using a delegate and binding it in your UMG blueprint. I prefer never to have my base classes talking directly to my hud classes at all. I just fire events based on state updates and my UMG blueprints can do whatever they like on that event with the data passed with the event. This creates a nice loosely-coupled system where changes to the UI don’t propagate downwards into your code. The event also does not have to be on your player controller, it can be on some central object like the game mode or a event manager custom component.

For example, you could add a delegate and property to MyGameMode.h. I’ll pass the player controller here, but maybe you want the player’s id, name, or pawn instead? Just pass whatever makes sense to your game. You can also use TwoParams or more if you need.



DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerDeathDelegate, AMyPlayerController*, PlayerController);

UCLASS()
class MYGAME_API AMyGameMode : public AGameMode
{
    UPROPERTY(BlueprintAssignable)
    FPlayerDeathDelegate OnPlayerDeath;
}


When your player dies, you can broadcast the event on the game mode from MyPlayerController.cpp, passing in this to represent the player controller that died, but again you could pass whatever data you need.



void MyPlayerController::IamDeadDeadDead()
{
    AMyGameMode* game_mode = (AMyGameMode*)GetWorld()->GetAuthGameMode();
    if (game_mode)
    {
      game_mode.OnPlayerDeath.Broadcast(this);
    }
}


Then in your UMG blueprint, just bind from your game mode, because you set BlueprintAssignable, to your OnPlayerDeath event and you’re good to go. This way you never actually have to know beforehand which player controller is going to raise the event, it’s all routed through a central event handler. Combine this with inheritance and it gets even more powerful and flexible and the sky is the limit.

Really thanks for the detailed answer.

I did this (ignore the squiggles)…

Shooter and PlayerHit are both Characters not Controllers.

Now I’d like to know how to pass the Name of the PlayerHit (Character) to the HUD so that it can display
**
You killed PlayerName**

I could be mistaken, but I believe the multiplayer player name is actually on the player’s state, not the character. ACharacter is a subclass of APawn, so you should be able to access PlayerHit->PlayerState->PlayerName.

But the problem now isn’t how to get the name of the player.

The problem is, once I’ve done that… now I have this Widget BP:

How do I pass the Player i passed to the event to the Widget’s ChangeText() function? (Yeah, now the function is taking a String as parameter, but I’ll change that)

Also, making this in the GameState won’t ruine the MultiPlayer structure? I want this to happen for every single player in the server lobby.

Every player in the lobby should be able to get printed out a string like “You killed Pizza” once he kills someone

I don’t see the issue. It’s simply a matter of getting the PlayerState from your Character and calling PlayerName on that. You should be able to do that all in blueprints just fine and then use that value in your Change Text function. I just tested it quickly, sorry no screenshot, but I was able to drag off a pin for PlayerState from a Character variable, and then another pin from that to PlayerName.