I found a fix to the problem on Movable surfaces, I overrid the OnRep_ReplicatedBasedMovement method on my character to be like this:
void ADeliveryShipCharacter::OnRep_ReplicatedBasedMovement()
{
// Following the same pattern in AActor::OnRep_ReplicatedMovement() just in case...
if (!IsReplicatingMovement())
{
return;
}
if (GetLocalRole() != ROLE_SimulatedProxy)
{
return;
}
// Skip base updates while playing root motion, it is handled inside of OnRep_RootMotion
if (IsPlayingNetworkedRootMotionMontage())
{
return;
}
GetCharacterMovement()->bNetworkUpdateReceived = true;
FGuardValue_Bitfield(bInBaseReplication, true);
const bool bBaseChanged = (BasedMovement.MovementBase != ReplicatedBasedMovement.MovementBase || BasedMovement.BoneName != ReplicatedBasedMovement.BoneName);
if (bBaseChanged)
{
// Even though we will copy the replicated based movement info, we need to use SetBase() to set up tick dependencies and trigger notifications.
SetBase(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName);
}
// Make sure to use the values of relative location/rotation etc from the server.
BasedMovement = ReplicatedBasedMovement;
if (ReplicatedBasedMovement.HasRelativeLocation())
{
// Update transform relative to movement base
const FVector OldLocation = GetActorLocation();
const FQuat OldRotation = GetActorQuat();
MovementBaseUtility::GetMovementBaseTransform(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName, GetCharacterMovement()->OldBaseLocation, GetCharacterMovement()->OldBaseQuat);
const FTransform BaseTransform(GetCharacterMovement()->OldBaseQuat, GetCharacterMovement()->OldBaseLocation);
const FVector NewLocation = BaseTransform.TransformPositionNoScale(ReplicatedBasedMovement.Location);
FRotator NewRotation;
if (ReplicatedBasedMovement.HasRelativeRotation())
{
// Relative location, relative rotation
NewRotation = (FRotationMatrix(ReplicatedBasedMovement.Rotation) * FQuatRotationMatrix(GetCharacterMovement()->OldBaseQuat)).Rotator();
}
else
{
// Relative location, absolute rotation
NewRotation = ReplicatedBasedMovement.Rotation;
}
// When position or base changes, movement mode will need to be updated. This assumes rotation changes don't affect that.
GetCharacterMovement()->bJustTeleported |= (bBaseChanged || NewLocation != OldLocation);
GetCharacterMovement()->bNetworkSmoothingComplete = false;
GetCharacterMovement()->SmoothCorrection(OldLocation, OldRotation, NewLocation, NewRotation.Quaternion());
OnUpdateSimulatedPosition(OldLocation, OldRotation);
}
}
The content of this method is the same as the ACharacter version but I removed the part about keeping the Character vertical, and that’s it !