Is this Multiplayer movement logic correct?

Ok, so I’m self taught at networking game stuff. I started in Unity (mirror) and I thought I had a pretty solid understanding of how to execute things from client to server, or from server to everyone, etc.

Let me start with how I understand it, as plainly as I can put it.

The Server (as a player) essentially just needs to Multicast their actions to everyone. Since they are the server, they just need to tell everyone what they are doing.

The **Client **(as a player, obviously) needs to run the action locally, and also tell the server to tell all other clients that this action happened (very loose explanation there).

With that in mind, I made the attached logic. It was working just fine until I tried to play this over the internet with a friend… and then we notice client jitter. Locally you can almost never see the jitter happen, but while I was learning this logic I ran into the same exact jitter and fixed it by running it through the Client custom action.

To be clear, the Client runs a custom event that is “Executes on Server” that calls the same command that the server uses to successfully move. I must be missing something simple/fundamental.

Thanks for the help in advance.

Ah, I figured out my issue.

I had all of my movement custom events not set to Reliable. My understanding now is that the checkbox for reliable means it’s either going to be TCP (reliable) or UDP (unreliable). I might be misunderstanding the exact meaning of the reliable checkbox, but it fixed my issue to make these network events reliable.

Ok, I lied. I still have jitter when playing over the internet. Is there some way to fix that?

You can achieve this in several ways.

Simpler method:

Or if you need to replicate a variable (using RepNotify):

You change the variables first on the server (not multicast). And for max movement speed you need to change it on the server and client side (as shown in the first example).

Thank you so much for your reply, Mr. Wood. I’m going to go through and modify all of my movements.

Here is a question: When would one use multicast? The game will be showing all players that the other players have jumped, sprinted, etc. Does that information for the players all get replicated by default to all other players?

EDIT: Or is repnotify the way to replicate to players for this type of thing?

Walking and jumping works out of the box for replicated actors. If you want to change max walk speed you need server authority which means that variables and character movements must be changed on the server first.
If you set some variable to Replicated or RepNotify you change it only on the server (it’s replicated so other client will receive variable changes from the server).

For bool variables (true/false) I almost always use RepNotify as well as for some other variables.
If I want to replicate something often, such as the speed of a car, so that other players can know the speed of other players, then I use a multicast.
It may not be the best example, but for most variables it is very practical to use RepNotify, because you can define in RepNotify function what will happened on the server only and on the other clients by using Switch has authority (authority node = server, remote node = client) when some variable changes.

Alrighty, well I tried replicating your logic in my controller and I’m having worse results than before.

Attached is the logic I’m using. Neither side is increasing speed, only the server sees the animation updates. I’m definitely missing something. Image “Capture” is the logic inside my player blueprint, and the RepNotify is within my Animation blueprint.

You don’t need Cast to AnimBP on the server.
In your character variable “Running” should be set to RepNotify or Replicated.
In your AnimBP event graph you need to set reference to your character and set variable Running in UpdateAnimation event (if you are using it in your AnimBP).
Something like this (animBP):

My variables are inside my AnimBP, so to set them I was casting to them.

Should I make player variables that refer to the player? Is that required for what I’m trying to accomplish? I am trying to set the AnimBP variables to trigger the animations for everyone on the server.

Yes. It’s not recommended to replicate variables inside AnimBP. Try to use server side logic and functions in your Character BP and use variables as references in your AnimBP similar to the image above

Hi, couple of things

(-) AFAIK animation blueprints don’t replicate, so it doesn’t make sense to have replicated variables there

(-) If you think that you have slow replication (and not just not working replication due to bugs in your code), then try to increase the network bandwidth limit in the config files (AFAIK default is 5 kilobyte per second)

(-) Don’t use multicasts for replication things like movement modes, only use them for one shot events (repnotify will update if an actor was not network relevant for a client and later becomes network relevant and will also update if a new client would join the game. Multicast won’t, so if the client didn’t get the mulicast when it was executed, it never will -> in progress join won’t work and you will get problems if you use network relevancy)

(-) Instead of having one boolean variable for every possible movement type, think about using an enum. So you could make an enum that contains values like jog, run, walk,… then you only have one variable which is better for performance (only need to replicate one variable) and is easier to maintain/read. For the movement speed you can then make a map from the movement enum to float. Also you can then inside the repnotify function of the movement enum send the new movement enum value (e. g. via interface) to your animation bluprint, therefore removing the need to query the movement enum on tick.

You guys are helping me learn! I had no idea about this.

No, I was absolutely confident it was a code issue and me not quite understanding what was going on.

I spent hours working out logic in my movement controller for my custom character. The first “smooth” success I had was to call a multicast on the server from the client. I ran into a lot of lag once I played with a friend over the net and now I am realizing I have to revamp the movement logic.

@MrWood for this as well, I have modified the code to use a replicated movement boolean from the player blueprint and referenced the “Running” boolean within the AnimBP to update as you had shown. It seems like I have covered my based for player movement and replication, but now I need to finish the rest of my logic with my new understanding and see if I run into issues.

Before my first reply, I had actually fixed another error I had with mad jitter… I had a few components replicated under my character that should not have been, and I had not replicated the physics of the mesh… so that was another issue I had run into. I practically modeled my character based off of the movement logic in the UE ThirdPersonCharacter template blueprint, and now I’m trying to add more things.

You’re absolutely right. For now, I’m just trying to grasp the concept of the logic of multiplayer things, so I’m making it very obvious in the code so I can solidify my understanding a bit more. Later projects would definitely be considering other things for controlling animation triggers, like enum.

I haven’t seen anything posted that considers client responsiveness. Say for example the player has a high ping (250ms) which is all to quite common in multiplayer games. In all examples given this player would have a 250ms+ delay before they started sprinting locally.

What I try doing wherever possible is make the logic deterministic and apply it locally first (responsiveness), then update the server.

With all that said, would it be wise to use multicast to tell everyone the player has crouched? I shrink the size of the capsule collider manually but it’s a “one time thing” until they uncrouch.

No. There’s no point in telling another player you did something if they’re on the other side of the map. “Relevancy”! Let the server decide who gets the change. You just need to tell it.

Alright, well I feel like I learned enough to know that I don’t know anything. Thanks for everyone’s help. I’m starting over from scratch and seeing if I can actually get a grasp with this god forsaken replication.

Most have issues with replication because they don’t understand the client-server model. In most cases all you need to do is tell the server and it will handle telling everyone else.

I’m definitely having a hard time grasping the actual logistics. I’m going to be spending my free time experimenting with much smaller replication practices, plus including the network simulation for average network so I can have some kind of realistic expectation from the logic in my code. Trying to deterministically replicate on client and server is great, but it’s difficult to know what is actually being replicated by default, and what needs to be manually replicated.

For example, the default ThirdPersonCharacter blueprint has it’s AnimBP controlling the “Running” and “Jumping” via tracking movement. All automatic, and replicated because of the checkboxes “Replicates” and “Replicate Movement” on that character.

The moment you move the control of the Running/Jumping animations out of the AnimBP and into the player controller, you end up realizing that the server does replicate “naturally” to everyone else, and the clients need extra logic.

My biggest issue is that I spent a good week of my free time trying to piece together everyone else’s experience, plus Unreal Docs, all to get an understanding of how replication works at a very basic, fundamental level… and now I’m realizing that the whole “Multicast” thing is not used as often as I thought.

I’m really going to look into how to work with RepNotify and booleans and see if that helps. It makes sense that the RepNotify would be the best because you update it on the client, and it tells everyone “hey, this updated, do this” instead of “hey, everyone, including the guy that sent the update request, update”

At least that’s my laymans understanding.

Capsule Movement Component (CMC)
Basic movement (WASD), Mouse Pitch & Yaw, Jump, and Crouch are the only things that replicate. “IF” you use the CMC functions. Anything beyond that you have to replicate.

Sprinting, custom crouch, prone, swimming, strafe jumping, climbing, speed changes etc you will have to set up your own replication. The most straight forward approach would be to use Booleans as “states” which will/can also be used in the animation BP/Graph/state machines. see previously posted sprint example.

You are more than welcome to DM me or hop on discord if you questions.

For perhaps a better understanding… imagine that you have chest that can be opened by a client (with repNotify). When another player connect to the server (or player who was far away, not relevant) he will receive the update about chest (via repNotify) when he became relevant for that actor.

As for the priority of whether to put the functions first on the client and then on the server, according to my logic, since there is small delay on the server (commands are sent remotely), it is probably better to perform first on the server and then on the client. The client will not see any difference in repositivity. Although this won’t have much of an impact, because all will be probably executed in the same tick on the client side.