Characters don’t replicate correctly while standing on a moving platform (= GetMovementBase()).
This is especially bad when the platform also rotates, like a Viking ship theme park ride (e.g. a very big swing that the player can walk on).
Enabling “bIgnoreClientMovementErrorChecksAndCorrection” and “bServerAcceptClientAuthoritativePosition” in the character movement component makes movement for clients themselves playable, but the movement is not replicated correctly to the server and other clients:
All connections see other characters not standing still while on the platform, but jitter around heavily.
Is there a way to fix or at least solve this in UE4.27?
From trying around there are several things that don’t work correctly here:
- When standing on a platform, the relative location to that platform is not replicated or at least not used to compute the world location. When I manually replicated the capsule’s bottom location, relative to the platform, computed the world location from it and the set the character’s location to that value, the location was stable. The mesh was still jittering though, because:
- “SmoothClientPosition()” and the two function it calls, don’t take the platform’s movement into account, resulting in the mesh stuttering even when I compute the capsule’s position correctly (see point 1).
[Attachment Removed]
Hi,
How are you handling replication of the platform’s movement?
I believe a common solution for this kind of problem is to forward predict the motion of the platform on the client, in order to account for the fact that the client’s character is moving predictively. More info can be found in these threads:
[Content removed]
[Content removed]
Thanks,
Alex
[Attachment Removed]
Hej,
For the swing I was simply replicating the axle’s local rotation and lerping the value on clients.
This results in the swing moving smoothly.
The client can jump on and move around it. Characters don’t stand still though. Both the client’s own character as well as other character shake around.
When I add ping and velocity extrapolation, it become completely unplayable. The server character jumps around more heavily for the client and the client is unable to even jump onto the swing.
If I enable “bIgnoreClientMovementErrorChecksAndCorrectionEffectTag”, it becomes perfectly playable for the client itself. BUT for a client all other players shake heavily. Even more than before.
For the server everyone is stable.
But there can also be desynchronization, where the character positions no longer match at all.
This is the code I use, which is from the engine’s physics replication:
float ServerAngularSpeed;
FVector ServerAngularVelocityAxis;
ServerAngularVelocity.ToDirectionAndLength(ServerAngularVelocityAxis, ServerAngularSpeed);
FQuat TargetQuat = ServerRotation;
if (!FMath::IsNearlyZero(PingExtrapolation, 0.01f))
{
float ExtrapolationDeltaSeconds = GGNet::PingSecondsOneWay(this) * PingExtrapolation;
FQuat ExtrapolationDeltaQuaternion = FQuat(ServerAngularVelocityAxis, ServerAngularSpeed * ExtrapolationDeltaSeconds);
TargetQuat = ExtrapolationDeltaQuaternion * ServerRotation;
}
FQuat CurrentRotation = Axle->GetRelativeTransform().GetRotation();
FQuat NewRotation = FQuat::Slerp(CurrentRotation, TargetQuat, AngleLerp);
Axle->SetRelativeRotation(NewRotation);
float AngularDifference;
FVector AngularDifferenceAxis;
FQuat DeltaQuat = NewRotation.Inverse() * TargetQuat;
DeltaQuat.ToAxisAndAngle(AngularDifferenceAxis, AngularDifference);
AngularDifference = FMath::RadiansToDegrees(FMath::UnwindRadians(AngularDifference));
if (!FMath::IsNearlyZero(AngularVelocityCoefficient, 0.01f))
{
FVector NewAngVel = ServerAngularVelocity + (AngularDifferenceAxis * AngularDifference * AngularVelocityCoefficient * DeltaSeconds);
FVector DeltaRotation = NewAngVel * DeltaSeconds;
Axle->AddRelativeRotation(FRotator::MakeFromEuler(DeltaRotation));
}
Changing the swing’s tick group doesn’t change anything.
[Attachment Removed]
Hi,
Thank you for the additional information.
In that case, you may want to try the approach of forward predicting the movement of the platform on the client. Instead of lerping the position/rotation on the client to the last position received by the server, you could use estimated latency between the client and server to move the platform ahead of the last received transform, better approximating where the platform currently is on the server.
Thanks,
Alex
[Attachment Removed]