Multiplayer Timing Out

Hey guys,

So I’m testing out multiplayer for my game using local-host settings… Both clients are on the same computer, but for some reason I keep receiving the error “LogNetPlayerMovement: Warning: CreateSavedMove: Hit limit of 96 saved moves (timing out or very bad ping?)” despite the fact that nothing computationally heavy is occurring.

When that error occurs, there’s also a fair amount of lag that accompanies it. Anyone know how I can go about fixing this?

What framerate is the game running at? If it’s running too high or if you have high latency, the character movement system is probably sending too many moves to the Server and they can’t be acked or corrected quickly enough.

This can also occur if you are modifying the movement of the character and are preventing CanCombineMove() from returning true in Character Movement. By default Character Movement will pack multiple moves together to prevent this overflow issue.

@TheJamsh, how can I go about checking the frame rate? I’m not doing anything special with the character movement, so I’m hoping that’s the issue.


You can just do stat fps in the console to show framerate.

Yeah I don’t know if it’s tied to FPS or not. If it helps at all, essentially what happens is that the client sees the host’s character just running away infinitely. Whereas the host sees everything replicated perfectly. Not sure if you have any other suggestions @TheJamsh?

other thing you can do is just quick start the thirdperson project, and then just do a server with 2 clients and see if the issue also happens there. This would tell you if something is seriously wrong with your computer and unreal, or if its just your project/code/movement code in your project that is the issue.

Are you sure the players are properly possessing the characters? The Client shouldn’t be running any movement sims for the host, so it’s a bit odd that you’re seeing that.

@TheJamsh I’ve been able to sort of trace down where this is happening. Basically, I’m calling the below function which is a Client-side function used to initialize the values of the sidekicks in our game after they’re spawned from a server-side function which is responsible for actually spawning the actor.

The game will act up when any of the other lines of code are uncommented except for the lines which are setting Abilities 1-4 (not the tags, just the abilities). So basically I can only set the variables Ability1-4. Any idea why this might be? All of the variables are set as “Replicated” and have been setup in the GetLifetimeReplicatedProps function. There realistically shouldn’t be any difference between setting any of these variables.

void AMonster::FinishSpawning_Implementation(FMonPlaceholder Placeholder)
{ this->Health = Placeholder.Health;
  this->Stamina = Placeholder.Stamina;
this->Nickname = Placeholder.Nickname;
this->Species = Placeholder.Species;
this->Level = Placeholder.Level;
this->XP = Placeholder.XP;
this->XPForNextLevel = Placeholder.XPForNextLevel;
this->Aggressiveness = Placeholder.Aggressiveness;
this->CanFly = Placeholder.CanFly;
// Fetch the Gameplay Ability classes.
if (Placeholder.MoveTags.Num() >= 1)
  [INDENT=2]this->Ability1 = MovesDataTable->FindRow<FMoveStruct>(Placeholder.MoveTags[0], FString(""), true)->AbilityClass;[/INDENT]
  if (Placeholder.MoveTags.Num() >= 2)
  [INDENT=2]this->Ability2 = MovesDataTable->FindRow<FMoveStruct>(Placeholder.MoveTags[1], FString(""), true)->AbilityClass;[/INDENT]
  if (Placeholder.MoveTags.Num() >= 3)
  [INDENT=2]this->Ability3 = MovesDataTable->FindRow<FMoveStruct>(Placeholder.MoveTags[2], FString(""), true)->AbilityClass;[/INDENT]
  if (Placeholder.MoveTags.Num() >= 4)
  [INDENT=2]this->Ability4 = MovesDataTable->FindRow<FMoveStruct>(Placeholder.MoveTags[3], FString(""), true)->AbilityClass;[/INDENT]
// Fetch the Gameplay Ability tags.
if (Placeholder.MoveTags.Num() >= 1)
  [INDENT=2]this->Ability1Tag = Placeholder.MoveTags[0];[/INDENT]
  if (Placeholder.MoveTags.Num() >= 2)
  [INDENT=2]this->Ability2Tag = Placeholder.MoveTags[1];[/INDENT]
  if (Placeholder.MoveTags.Num() >= 3)
  [INDENT=2]this->Ability3Tag = Placeholder.MoveTags[2];[/INDENT]
  if (Placeholder.MoveTags.Num() >= 4)
  [INDENT=2]this->Ability4Tag = Placeholder.MoveTags[3];[/INDENT]
this->Element1 = Placeholder.Element1;
this->Element2 = Placeholder.Element2;

// Update the Details Widget with our health and species
this->DetailsWidget->UpdateProgress(this->Health / this->MaximumHealth);

if (this->GetBBComponent())
  [INDENT=2]this->GetBBComponent()->SetValueAsObject(FName("SelfActor"), this);[/INDENT]

If the values are replicated then you shouldn’t be setting them in a client-side function at all, you set them Server-Side and rely on replication to fill out the properties client side. It’s hard to say to be honest, this looks like something very specific to your game.

FinishSpawning() may not be the best function name, there is already a FinishSpawning() function in AActor which is used for low-level spawning stuff by the engine.

Based on code comments I can’t tell if you’re using the engines Gameplay Abilities System too, but if you are it’s not meant to be used like that. There’s a whole specialised subsystem for managing and assigning abilities to something.

Hey @TheJamsh, the system that we’re creating involves a set of 4 moves that can be swapped out. We have another function that actually grants access to those abilities that are being setup in this function. This was the best way we could figure out to achieve this skill-tree type system. Definitely open to any input you might have on that.

I will look some more into setting them server-side :slight_smile: Thanks.

@TheJamsh, so if I set a variable in that server-side function that is set to replicate, can I not use ReplicatedUsing? The issue is that I need to perform some actions once the variables are replicated to the client.