MiddleCodeCommonNot answered yet
How do you smoothly rotate an actor to face a moving target each frame?
Inside an actor's Tick, smoothly rotate it each frame so its forward axis faces TargetActor, which may be moving.
Constraints:
do not snap and do not lerp FRotator components by hand.
- Build the desired rotation from the direction to the target (forward = X axis).
- Ease toward it framerate-independently — pass
DeltaTimeinto the interpolation, - Bail out safely when the target coincides with the actor's own location.
void AEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// your code here
}
Write the implementation.
Build the desired rotation with FRotationMatrix::MakeFromX(Direction).Rotator() or (Target - Self).Rotation(), then ease toward it with FMath::RInterpTo(Current, Desired, DeltaTime, Speed) and apply it via SetActorRotation.
- ✗Snapping with
SetActorRotationto the target rotation, skipping interpolation entirely - ✗Forgetting to pass
DeltaTimetoRInterpTo, making turn speed framerate-dependent - ✗Linearly lerping
FRotatorcomponents and getting a long way around past 180 degrees
- →How would you clamp the turn so the actor only yaws and never pitches?
- →Why is
RInterpTopreferable to linearly interpolatingFRotatorcomponents?
Smoothly rotating toward a target
void AEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!TargetActor)
return;
// Direction from self to the target in world space
const FVector Direction =
(TargetActor->GetActorLocation() - GetActorLocation()).GetSafeNormal();
if (Direction.IsNearlyZero())
return; // target coincides with our location
// Desired rotation: the X axis (forward) faces the target
const FRotator DesiredRotation = Direction.Rotation();
const FRotator CurrentRotation = GetActorRotation();
// Framerate-independent smooth interpolation
const FRotator NewRotation = FMath::RInterpTo(
CurrentRotation, DesiredRotation, DeltaTime, RotationSpeed);
SetActorRotation(NewRotation);
}
Key points:
Direction.Rotation()builds anFRotatorwhose X axis (forward) points at the target.RInterpTotakesDeltaTime, so the turn speed is identical at any frame rate.RInterpTofollows the shortest path and never "wraps around" past 180°, unlike component-wiseLerp.
To rotate only horizontally (typical for characters), zero out pitch and roll:
FRotator DesiredYawOnly = Direction.Rotation();
DesiredYawOnly.Pitch = 0.0f;
DesiredYawOnly.Roll = 0.0f;