Posting here as well as on the Unreal Engine subreddit (not sure which one is more popular)? So I am creating my own Character and CharacterMovementComponent Classes based off this wonderful video, and wanted to add in smooth crouching, so I override Crouch and UnCrouch with my own implementation that calls Play and Reverse on a Timeline (in C++) that then calls a custom CrouchUpdate event (in BP) which handles lerping the half height and z offset.
The issue I’m running into is that while it looks great, it isn’t synced, even with no latency or packet loss. And then when I turn on 1000 ping and 15% packet loss, movement is slightly off, but when I crouch it goes wild, flip flopping between crouched and uncrouched and getting stuck in the wrong mode.
How do I sync the timeline with no latency or packet loss? And how do I protect against packet loss?
Is it possible that I need include some client prediction code?
Relevant Code (please ask for more if necessary):
void UFPSCharacterMovementComponent::Crouch(bool bClientSimulation)
{
if (!HasValidData())
{
return;
}
if (!bClientSimulation && !CanCrouchInCurrentState())
{
return;
}
if (CharacterOwner->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight() == CrouchedHalfHeight)
{
if (!bClientSimulation)
{
CharacterOwner->bIsCrouched = true;
}
return;
}
// Not sure if necessary
//if (bClientSimulation && CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy)
//{
// // restore collision size before crouching
// ACharacter* DefaultCharacter = CharacterOwner->GetClass()->GetDefaultObject<ACharacter>();
// CharacterOwner->GetCapsuleComponent()->SetCapsuleSize(DefaultCharacter->GetCapsuleComponent()->GetUnscaledCapsuleRadius(), DefaultCharacter->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight());
//}
if (!bClientSimulation)
{
CharacterOwner->bIsCrouched = true;
}
bForceNextFloorCheck = true;
CrouchTimelineComp->Play();
}
void UFPSCharacterMovementComponent::UnCrouch(bool bClientSimulation)
{
if (!HasValidData())
{
return;
}
ACharacter* DefaultCharacter = CharacterOwner->GetClass()->GetDefaultObject<ACharacter>();
if (CharacterOwner->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight() == DefaultCharacter->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight())
{
if (!bClientSimulation)
{
CharacterOwner->bIsCrouched = false;
}
return;
}
if (!bClientSimulation)
{
// Test for uncrouch
CharacterOwner->bIsCrouched = false;
}
CrouchTimelineComp->Reverse();
}