Quick answer: Interpolate rotation between received network updates. Quantize the replicated FRotator to save bandwidth. Don’t apply received rotation directly each frame; lerp toward it.
Multiplayer FPS. Your own aim is smooth. Remote players’ aim snaps every 30ms instead of moving continuously. Network rotation updates arrive at a discrete rate; rendering is continuous. The mismatch is visible.
Interpolate Toward Received
UPROPERTY(Replicated)
FRotator TargetControlRotation;
FRotator CurrentRotation;
void ACharacter::Tick(float Dt) {
Super::Tick(Dt);
if (GetLocalRole() == ROLE_SimulatedProxy) {
CurrentRotation = FMath::RInterpTo(CurrentRotation, TargetControlRotation, Dt, 15.0f);
SetActorRotation(CurrentRotation);
}
}
RInterpTo with rate 15 smoothly approaches the target rotation. Network updates change TargetControlRotation; rendering reads CurrentRotation. Continuous motion between discrete updates.
Quantize for Bandwidth
FRotator is 12 bytes uncompressed. Use NetSerialize with quantization:
USTRUCT(BlueprintType)
struct FQuantizedRotator
{
GENERATED_BODY()
UPROPERTY()
uint16 Pitch;
UPROPERTY()
uint16 Yaw;
FRotator ToRotator() const {
return FRotator(
(float)Pitch * 360.0f / 65536.0f,
(float)Yaw * 360.0f / 65536.0f,
0
);
}
};
4 bytes vs 12 bytes. Precision is 0.005 degrees, indistinguishable to players. Roll often unnecessary for FPS pawns; skip it.
Update Frequency
Set NetUpdateFrequency = 60 on the pawn for smooth updates. Default 100 is overkill; 60 matches typical render rate without overloading the network. NetMinFrequency = 30 ensures at least one update per 33ms even when nothing changes (keeps interpolation alive).
Forward Vector vs Rotation
For just aim direction (no roll), some games replicate the forward vector as a float3 then construct rotation locally:
FVector ReplicatedAimDir; // 12 bytes uncompressed, or quantize as 3 int16s
FRotator aimRot = ReplicatedAimDir.Rotation();
Cleaner semantically; same byte cost as quantized rotator.
Verifying
Watch a remote pawn turn in a circle. With interpolation, motion is smooth. Without, you see ~30 Hz steppy rotation. Net Profiler should show 30–60 updates/sec for the pawn at typical NetUpdateFrequency.
“Replicate the target, interpolate the current. Quantize for bandwidth. Network rotation feels smooth.”
Interpolation rate is a tuning parameter. Higher = snappier; lower = smoother but laggier. 12–20 is a typical range for FPS.