Multiplayer Health Bar

Hey,
I am just starting out and trying to implement a multiplayer shooter. When there is only one person, the healthbar works just fine, but when the second person joins, it’s health bar doesn’t update anymore.


I suspect, it has something to do with Player Index 0, but I am not sure how to fix that.
Thank you very much for your help!

Hey, will probably need a little more information than this. When you say multiplayer are you creating a networked game so the second player is on a remote client, or is it local multiplayer? Also which health bar stops working is it the health bar of the first player or the new player? Also what blueprint is the screenshot from the player controller? Would also be good to add a screenshot of where Get Percent 0 is called from.

Yep Player Controller/Character(0) is always the local clients first/main character to be spawned with subsequent indexes being incremented for each new player so Player Controller(1) will be the second character… So you’d probably want to enter Player Index 1 for the second character.

Personally I use manual references for the players. So not sure where you’re calling the above blueprint, but instead of the Get Player Character Cast to… nodes, if this code is in your character blueprint just use the “self” node instead. If the above code is somewhere else, eg. your Game Instance, Game Mode, or widget blueprint, you could pass it a reference to the player controller/character and use that.

Alright, first of all thank you very much. I will clarify as much as I can.
I want to create a networked game, so the second player is on a remote client. And yes, the health bar of the new player stops working. I use a widget for the life bar:

](filedata/fetch?id=1840776&d=1607461266)
Binded to the progress bar is the following function (The function is defined inside the widget):

And I add it to the players viewport like this:

Is there anyway, I make the widget a subclass of the player character, so that I could call the variables directly?

Update: The player seems to be taking damage just fine, when I put the health as text above the player, the host can see his health:


However the other way around this is not true:

The health bar just doesnt seem to update, also the text doesn’t update, so is this maybe an issue with the way the server is set up?:

Update, I have now set the variable to “replicated” and it works. However, when creating the BloodVignette Widget, it only appears on the server, not in the clients viewport.
I use this to take damage:


Where at the end of the function Take Damage I call the following:

CreateBloodVignette.PNG
Which adds the Blood Vignette to the viewport.


This is the Event Construct for the Blood Vignette Widget.
I understand, that the AnyDamage Event only runs on the server, but how can I still add the widget to the clients viewport?

The issue with doing it without the server run AnyDamage Event is, that I dont know, how to do the retriggerable delay inside a function.

Can anyone help?

Hey, try to be clearer with your explanations (it helps people understand what’s happening in your code and more importantly helps you clarify in your own mind exactly what’s happening with the different objects and classes that are involved and how they are communicating…

I’m assuming the damage vignette appears on the host-client screen when the host-client takes damage, but doesn’t appear on either host or remote client when the remote player takes damage?
I’m also assuming the TakeDamage code is in the player controller or player character blueprints?

There are a couple main ways to pass data from what is happening on the server to the remote client, by replication or by creating a Custom Event set to “Run on Owning Client”:

First as you say you can create a player controller/character variable called “TakenDamage” that you set to replicated, then in that classes “Event Tick” for example you can check if this variable has been set true, and if so run your create damage vignette code.

Another option is to create a custom event:

  • When players (host or remote) join a multiplayer game session, the Game Mode “Event PostLogin” event is called automatically. This event includes a reference to the joining player controller (host and remote). Save these player controller references in your Game Mode blueprint.
  • In your Player Controller blueprint you can then create a Custom Event set to “Run on Owning Client” and add your damage vignette code to run from that event.
  • Then on the server side whenever a player takes damage call your Custom Event passing the player controller reference you saved in Game Mode and it will run on the client to create the vignette on the remote client screen (you might even be able to try from your Event Any Damage calling your Custom Event passing it a reference to self, haven’t tried it but might work).

Img1: Player Controller Event Tick
Img2: Player Controller Custom Event (remote exec)
Img3: Game Mode Custom Event call

Easiest way to understand this IMO!!!

I will use RUN as an example

You can ONLY use custom events for anything multiplayer. Forget functions and macros (I could be wrong but its less confusing like this)

Every multiplayer action will have the exact same 3 Custom Events

  1. ****Call
  2. ****Server (Run on server and Reliable Ticked)
  3. ****Multi (Multicast and Reliable Ticked)

Make an input for run or use Key Left Shift on pressed - RunCall

in RunCall - Switch has Authority - authority goes to RunMulti and remote goes to RunServer

in RunServer this goes directly to RunMulti

in RunMulti set max walk speed or whatever you want.

Simple and it works (might not work for everything but hasn’t failed me yet.

Run4.JPG

Hey, thanks for the amazing answers.
As far as I understand multicast, it casts to all clients right? So wouldn’t all clients start running then? Or does just one start running and the other clients can see him running?

Okay @Nobodikilla , so I played around with it for a bit and ran into a problem:

This is my code for damaging someone (inside ThirdPersonCharacter) and it seems to be working correctly. DamageCall keeps getting called twice, once from the server and once from the client, so when the host client gets damage, its correct, but when the client takes damage, the damage function is called twice and he gets twice the damage. In my example, I let the player walk into a cube and on overlap he gets damage, as you can see in the following picture, the player is registered twice if he is not the host:
ServerClientCall (2).PNG
And as this is registered, the function gets called twice. When I just disconnect the remote part of switch has authority it works again, because only the server call gets through:

Is this the wrong way to go, or does it work just fine?

As I aspected, there are some more problems coming up. When calling the DamageCall event in my weapon Blueprint like this:

Only the host can do damage, while the other clients can’t. Even if I reconnect the remote part of the Switch Has Authority, it doesn’t work.

I have had issues with breaking hit results and trying to use “does implement interface” spent a whole day and then figured out it doesn’t always work. I typically use “Does actor have tag” coming from hit actor, then you have to add tags to BP but its easy enough. To me it seems to be the most reliable. Or just run the red wire from your cast and get rid of the display name stuff. I will try playing with the overall issue and se what i get

I tried this and it worked well Stamina started at 100 default. The part that says is locally controlled just stops all clients from displaying the message. That node is useful other times also, i just dont really know when. Its possible you have issues reducing the armor value or maybe you accidently call a function again, maybe the cube overlap is getting vcalled twice. Or some other silly mistake that costs you a full day like I always do :slight_smile: I just used a key press to test the setup and avoid confusion.EX1.JPG

Looking back at your code I think MAYBE your print string is throwing you off? The print string can be tricky on multiplayer because it prints on all clients. Its POSSIBLE that you are getting correct results and not knowing it. Look into UI Bindings and make a health meter quick to verify?

Thanks for the hint @Nobodikilla, Is Locally controlled is amazing!!! However the host is still the only one who can deal damage. I have an error message, however I don’t really understand the message:


Because of this, the other players cant deal damage. This is how I call the function:
From Weapon Blueprint I call CallDamage like this:

Notice, it only runs when the Hit Actor Name contains ThirdPersonCharacter.
Inside my character blueprint I do this:

Thank you so much for your help!!
Could the issue possibly be, that the players are indexed differently on the client side then on the server side? So when I use the hit actor, it will not be the same on the server side or something like that.
Also, I didn’t quite understand what you meant by adding tags. Do you mean seperated tags for each player or 1 tag for all?

I’m going to be honest. I was wrong. The method of switch has authority, then run on server or multicast is problematic at least. The reason I was using that is because I don’t think you can call server events from clients. But it appears that sometimes you can? I’m still learning this also and there are not a lot of good resources I can find.

Maybe try getting rid of the switch and just run on server?

Check that your variables are replicated (I don’t know if they should be or not) probably LOL

Event Any Damage is a server only event. So if your using that at any part of this you could be getting errors from that.

Player index is for LOCAL couch style multiplayer I believe. I think it returns 0 as server and 1 for all clients. I don’t think it will be much help.

It seems like your player controller (which owns your pawn) is owned by server also so you could try running things on server there too.

I think the multicast setup I showed is good for explosions. You wouldn’t multicast from every client because every client would then send to every other client. Maybe for variables you can go straight to run on server?

This link wasn’t super helpful but at least he tried to help.
UE4 Networking Compendium.

https://www.google.com/url?sa=t&source=web&rct=j&url=http://cedric-neukirchen.net/Downloads/Compendium/UE4_Network_Compendium_by_Cedric_eXi_Neukirchen.pdf&ved=2ahUKEwj8h7zVgNHtAhWVGc0KHe6cAmQQFjAAegQIAxAC&usg=AOvVaw26JglvIiA88TBUm_vwUwc0

this guy appears to know his stuff. I’m working through this tutorial hoping to learn some more

Get pawn owner then get player controller might do what you were trying to do with get player index

You mentioned using a cube to cause damage. I wonder if the cube needs to be replicated.