Attaching weapon differently for client that owns the player character

I have a simple multiplayer FPS project where I manually spawn pawns for each player as they log in (from the GameMode), have them be possessed by their respective PlayerController, and then I spawn a weapon for them, like so:

At the end of that screenshot I’m trying to notify each client that a new weapon was given to the player that joined, and if they are themselves, it should be attached to their first person arms instead of the third person mesh. I’m trying to notify with a Multicast event on the Pawn itself, like this:

I didn’t have problems when I was using default pawns, but now I’m trying to give the server more authority by having the GameMode handle spawning. The client doesn’t even receive the event when I print in it. I also tried adding a step by adding an event to the PlayerController which then acts on its Pawn, but it didn’t work either. I’m sure my approach is all wrong for this sort of feature and I need some guidance on my understanding of networking in general. Thank you all in advance!

Hey,
A multicast wont fire on all clients unless its called from a “Run On Server” event. In some cases a “Run On Owning Client” must be fired along side the multicast event so you can run your own client side logic and also replicate that to the rest of the clients as well.

A pretty simple and effective naming convention will always be easy for you to read and debug. I would personally create two custom events. I would name it just like you have it except I would call one ReceivePrimaryWeaponMulticast making it “Multicast” and the other ReceivePrimaryWeaponServer making it “Run On Server”. Most likely reliable for events like this.

From the server event call the multicast event. From the multicast event have your logic just like you have. Call the server event from wherever your execution starts. It would go something like this:

"Input Action> ReceivePrimaryWeaponServer

ReceivePrimaryWeaponServer> ReceivePrimaryWeaponMulticast

ReceivePrimaryWeaponMulticast> Your logic"

This works every time in most simple execution strings on each client and you will always know which one is which a lot easier when you have a ton of RPCs down the road.

Running your logic only on a “Run On Server” event will most likely end up with everyone getting the same weapon when the other guy is swapping out.

Thanks for helping me out. I think I did as you said, having the GameMode invoke a Run On Server event on the pawn which then calls the Multicast, but I’m still getting two print logs from the server when there are two players, I was expecting to see one from the ListenServer and one from the connected client. Here’s my script, I’m not sure if I understood correctly:

To be more specific, I was expecting to see the server print “Hello” and then the client print its own “Hello”, to confirm me that the code was actually running on the client machine for its own copy of the actor. Instead it’s the server printing two times.

I’ve had this issue as well. I seem to think that it’s because the server is executing it also as it thinks its also acting as a client. Which if you’re going for LAN that would be need to be the case. Networking can get very frustrating because it does weird stuff. A lot of trial and error on some things…

I find that in some cases I also need another custom event running the same logic that is Run On Owning Client but called right before or after the server event. I’d call it ReceivePrimaryWeaponClient.

You could try placing a branch before the print log on the multicast and get and check IsDedicatedServer? And out of false do nothing and run true into your logic and see if that clears it up. If you do that you may need that run on owning client event right after the server event.

Sometimes you need to just bypass certain parts if the logic with that branch check and just go around certain nodes, like widgets because they won’t load on server and throw up runtime errors. This has worked for me.

I always test in standalone mode with at least three clients to make sure the clients are replicating correctly and not being corrected by the local server which is also a client on LAN.

It seems that Play In Editor is correcting replication issues on some circumstances because everything is happening on the local machine. Building the network for a dedicated server setup will ensure that you are 100% solid that the server events are handled correctly.

I hope that helps. I went through a lot of hair pulling get everything to act right.

A user on Reddit gave me a more correct approach to this problem that doesn’t involve hacky delays to wait for the weapon actor to be replicated on every client before running code, I’m posting it in case someone else comes across this question in the future.

The weapon field on the Character should be replicated with notifications, so that all clients will attach it on the OnRepNotify event. It’s also more comfortable to be Exposed on Spawn so that when you spawn players in the GameMode you already set the weapon as you spawn them.

If, like me, you are running a ListenServer setup (and not dedicated) you also need to call a Run On Server event in BeginPlay of the Character to attach the weapon for the ListenServer, because the ListenServer doesn’t receive OnRepNotify events.

Here are some screenshots.

A generic function that switches between attaching on the first person arms or third person mesh depending on if the character is owned by the local player (there are many ways to do this, possibly checking on the current Controller is more appropriate):

That function is called OnRepNotify for all clients (except ListenServer):
Screenshot 2022-01-20 205021

This last snippet is to attach the weapon for the ListenServer, not needed for Dedicated Server setups:
Screenshot 2022-01-20 205033

It is odd that this solution works for you. It simply shouldn’t. Attach actor is a replicated event so it will override any attachments done on the client