The core of what’s going on is inside the update loop:
void AHeroPawn::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
...
MoveH(Velocity.X * DeltaTime * 50);
MoveV(Velocity.Z * DeltaTime * 50);
}
MoveH and MoveV simply move the sprite the amount passed checking if there’s a collision in between with simple overlap checks. I move the actor in the new position, check for collision and if it collides I move it back to the original position. Rinse and repeat.
The Velocity.X becomes zero as soon as I stop pressing the left or right key, but the pawn keeps moving. I exposed the value so that I can see it changing in the editor and it’s exactly zero when it still moves. There’s no fractions or rounding errors apparently.
The pawn is like shown there: