Hi there!
I’m working on an online game that requires grid movement. I’ve made the mistake of implementing locally first before worrying about the data sent to the server.
Here was my local implementation
unit->GetWorldTimerManager().ClearTimer(MovementTimerHandle);
// Desired Cell Location
FVector2D targetCell = playerCurrentCell + Input;
// Desired World Location
FVector TargetPosition = CellToWorld(targetCell);
TargetPosition.Z = unit->GetActorLocation().Z;
// Calculate the movement direction
FVector Direction = (TargetPosition - unit->GetActorLocation()).GetSafeNormal();
// Calculate distance and time required for movement
float Distance = FVector::Distance(unit->GetActorLocation(), TargetPosition);
// Start a timer to handle movement
unit->GetWorldTimerManager().SetTimer(MovementTimerHandle, [this, TargetPosition, MovementSpeed]()
{
float ElapsedTime = GetWorld()->GetDeltaSeconds();
FVector NewLocation = FMath::VInterpConstantTo(unit->GetActorLocation(), TargetPosition, ElapsedTime, MovementSpeed);
unit->TeleportTo(NewLocation, unit->GetActorRotation());
//unit->SetActorLocation(NewLocation);
if (FVector::Distance(unit->GetActorLocation(), TargetPosition) < KINDA_SMALL_NUMBER)
{
unit->GetWorldTimerManager().ClearTimer(MovementTimerHandle);
unit->TeleportTo(NewLocation, unit->GetActorRotation());
//unit->SetActorLocation(TargetPosition);
OnMovementEnded();
}
}, 0.01f, true);
}
This implementation is fine, however it won’t work with a dedicated server for obvious reasons.
I’ve read that AddMovementInput() is the preferred method of choice for online movement since its replicated and has built-in optimization (all thanks to the savedMove idea). So i’ve tried to implement my method of tile movement using AddMovementInput()
void AFighter::MoveToNextTile(FVector TargetPosition, float MovementSpeed) {
GetWorldTimerManager().ClearTimer(MovementTimerHandle);
// Calculate the direction to move
FVector MoveDirection = (TargetPosition - GetActorLocation()).GetSafeNormal();
// Start a timer to handle movement
GetWorldTimerManager().SetTimer(MovementTimerHandle, [this, TargetPosition, MoveDirection, MovementSpeed]()
{
bMovementTransit = true;
// Use AddMovementInput for replicated movement
AddMovementInput(MoveDirection, MovementSpeed, false);
if (FVector::Distance(GetActorLocation(), TargetPosition) < 5)
{
FighterMovementComponent->StopMovementImmediately();
SetActorLocation(TargetPosition);
bMovementTransit = false;
GetWorldTimerManager().ClearTimer(MovementTimerHandle);
}
}, GetWorld()->GetDeltaSeconds(), true);
}
however the movement is terrible, extremely laggy and not well optimized.
How can I fix this ? Is there something I don’t understand ?
I didn’t have this issue using SetActorLocation()/TeleportTo() locally, can I still use those and replicate the necessary variables even though these method are not safe for movement ? (can’t handle lag or packetloss, cannot combine two moves for reduced bandwith, etc…)
i guess the broader question is:
Should I default to using AddMovementInput() everytime I want to make an online movement ?
It has its benefit but my implementation of tile movement make it extremely unpleasant to move the character around, it’s not smooth at all.
Thank you for your understanding.