Looking for the most practical way to implement online grid movement.

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.