Replicating SetActorLocation() smoothly while SetReplicatingMovement is true?

I’ve been trying to do some custom movement lately in the form of a quick dash. Right now I’m checking if a variable is true each frame, and if so, I’m using SetActorLocation(); to move the player forward X distance. The problem is that, while it replicates, the replication causes the client to move around jagged on client-side. On the server it moves fine.

When I use this while SetReplicatingMovement(false); the replication of the custom movement is perfectly fine. This tells me that there might be some kind of conflict between my movement and the base movement. Does anybody have any ideas on how to prevent this conflict? If any more information is needed, I’d be glad to provide it.

I’m also having the same issue with many other forms of movement like ApplyWorldOffset(); and even LaunchCharacter();! This can all be solved by just making my own movement for everything. Of course though, I’d rather not reinvent the wheel of movement if I don’t have to.

It may be down to how the movement is played back. A jump forward would potentially play back like a teleport. Also, the rate of replication could be a factor here, the default being once per second. you might need to adjust this value to 10 or 1/10th of a second. and it might improve the movement.

1 Like

Thanks for the answer @beegeedee! I’ll be investigating what you said to see if it helps. I’ve already looked into the replication as you suggested, and I wanted to ask if this has to do with MinNetUpdateFrequency? It’s what makes the most sense to me but I noticed that it’s default value is 2 rather than the 1 I would expect.

Yes, that’s the one. It represents 1/updatefrequency seconds so 2 is once every 1/2s and 10 is a good number.

1 Like

Unfortunately it doesn’t seem that setting it higher helped any. Turning MinNetUpdateFrequency to 10 doesn’t have any visual effect on the jitter, same with turning it up even higher. Could you give me a bit more info on the teleport idea you were talking about?

For reference, I’ll leave some of the essential code on how I’m going about doing this:

/* When the following is true...  (Checks each TICK) */

if (IsDashActive) { Dash(); }

/* Activate the following... */

void ABrawlTownCharacter::Dash()
{
	FVector NowLoc = GetActorLocation();

	const FRotator Rotation = GetControlRotation();
	const FRotator YawRotation(0, Rotation.Yaw, 0);
	FVector NowForward = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

	const float DisForward = 900.0f;

	FVector NewLoc = NowLoc + (DisForward * NowForward);

 // I added this to try and smooth the movement but it didn't work.
	NewLoc = FMath::Lerp(NowLoc, NewLoc, GetWorld()->GetDeltaSeconds());
			
	SetActorLocation(NewLoc, true);

	if (NowLoc.Equals(NewLoc))
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Purple, FString::Printf(TEXT("Test F")));
	}

	Server_Dash(NowLoc, NewLoc);
}

void ABrawlTownCharacter::Server_Dash_Implementation(FVector NowLoc, FVector NewLoc)
{
	SetActorLocation(NowLoc, true);
}

You don’t want the MinNetUpdateFrequency to be higher than the maximum FPS you’re targeting, but 30 should be the max you need for a 60fps game and even 10 should do the job.

Since this doesn’t solve the issue, are you executing the dash in a single frame or is there messages being sent to the server for a series of steps? It’s more like a velocity change for a brief interval, say, speed burst of 5x normal max in a given direction for a period of 1/2 second or whatever you decide. This should then result in a series of server updates over n frames, depending on the client fps. e.g. 1/2 second boost would send increased velocity 30 times for a 60fps. The update MinNetUpdateFrequency of 10 should then show 5 updates over the 1/2 second period.

Remember, the movements should be done on the server and simulated on the client, then showing the truth on the replicated updates.

Have you tried asking about this on the discord too?

1 Like