Widget Get Owning Player Pawn returns the same player.

Hello there.

I am trying to implement a multiplayer health bar on top of each character.
First I want to make it simple and make it work locally on two players (Say 1 AI and the player )
I have a c++ class that looks like this :

I’ve made an event that I want to be used in blueprints and do stuff with the information provided from the event.
Next, I have is a BP base for the player logic, and two other child BP for two different characters(difference in models, animations, etc )

In the base BP, I add the health component and a health bar widget and it looks like this:

Structure :

Test print string inside the base class of player ( proper names get printed of damaged player and damage causer )

And finally, in the widget blueprint, I have the following scheme that updates the health bar on start and binds the OnHealthChanged event to a delegate that should update when the player / AI took some damage.

The problem is that the function “Get Owning Player Pawn” ALWAYS returns the same player, not the owner of the widget. My guess is it is because is name PLAYER PAWN (it means the local player ? so it always returns the same widget??? ). If it is like this, how can I get the Widget owner PER instance of the player BP?

What happens is if I attack the AI player, the UI never gets updated ( because its widget got the player owning pawn and a player can never hurt himself !!! ). But when I make a pain-causing volume, WELL, both widgets get updated( like it is the same widget, but with two instances).

Any help is appreciated. Thanks !!

GetOwningPlayerPawn like you discovered always returns the same local player pawn. In networked multiplayer you will need to add a separate TargetPawn variable and use that to get a reference to a specific pawn.

GetOwningPlayerPawn uses the PlayerController to get to the pawn and each client can only see their own PlayerController.

Yes, I found it out, but what happens in the case where I have a player and AI using the same BP widget? I said I want to make it work first locally (1 instance, standalone, no MP, no Servers, no Clients) I still have to manually set the Widget BP variable ( and bind it to the progress bar percentage variable ) from the player BP and set it as the owner ?

If each character creates their own widget then you will have a widget per character. Forget about the Owner of the widget it is irrelevant in this context.

  1. The character should have a widget component with a health-widget assigned.
  2. The character should have a health variable and a function that updates their health eg. HealthUpdate.
  3. On each HealthUpdate function call you update the health via the widget component->GetUserWidgetObject to reflect the change on the individual character widget.

Yes, I figured it out. For now, each character / AI has its own HealthComponent and HealthBar widget. They are all added through the blueprint, but i might add that through code later when i start doing the networking bits.

What I did now is :
base player class function (called OnBeginPlay)

https://puu.sh/FreFS/8fa9364299.png

And the health bar widget BP

https://puu.sh/FreGI/fe3b17a2e0.png

Do you think this is a clean solution? Just bind the event to the widget, instead of notifying it every time health changed, so I do not have to use GetUserWidget every time? :stuck_out_tongue:

You don’t gain much from having to bind the widget to an event dispatcher since you already have a hard reference to the widget within the widget component but if you are comfortable with event dispatchers then I suppose it is fine.
It is recommended that if you need to do bindings in a widget that you do it OnEventInitialized and not OnEventConstruct since Construct can potentially be called several times during the game.

You could also make the Widget component responsible for updating the UserWidget by making a Blueprint derived class from WidgetComponent and have it bind to the character and update the widget accordingly. Then the UserWidget is only handling its own visuals.

I try to keep UserWidgets as isolated from the rest of the logic as possible and use as few external references as possible within the widget. If a UserWidget needs to call Events elsewhere then I would use an EventDispatcher within the widget (like OnStartButtonClicked) and bind to this event externally.
By keeping widgets isolated they can be created by designers with limited Blueprint logic experience, furthermore you risk crashing the editor when doing DesignTime testing of the widget if it requires external references.

Thank you for the pointers! As I am still learning the workflow of Unreal and how to make things work in an efficient way this is really helpful to me! Cheers.