Download

InterpToMovementComponent Absolute Locations NOT Absolute

I decided to use UInterpToMovementComponent for some of my side-scroller moving props/enemies and I’ve had to do battle with this nasty little component. This component seems to work very well if I set the control points in the editor in an actor instance, but setting them at runtime in C++ got weird.

My goal was just to move the actor from its current location to a target location precisely to conserve the all-important side-scroller timing cycles, and this component seemed to be exactly what I was looking for.

This is the code that SHOULD be working:

void USomeGameFunctionLibrary::InterpToLocation(UInterpToMovementComponent* MoveComp, const FVector& Location, float Speed)
{	
	// clear out any existing control points
	MoveComp->ResetControlPoints();

	// set time
	MoveComp->Duration = Speed;

	// add first control point where owner currently is
	// NOTE: despite bPositionIsRelative=false, actor rotation affects locations.
	MoveComp->AddControlPointPosition(MoveComp->GetOwner()->GetActorLocation(), false);

	// Add control point destination
	// again, target location is affected by actor rotation despite absolute location
	MoveComp->AddControlPointPosition(Location, false);

	MoveComp->BehaviourType = EInterpToBehaviourType::OneShot;
	
	MoveComp->FinaliseControlPoints();

	MoveComp->RestartMovement();
}

Despite using absolute position, the initial rotation of the actor will rotate these locations. Ie. if actor has 90 yaw rotation and target is 0,100,0 then the target will actually become 100,0,0.

It took me hours to figure out that the locations were actually being affected by the actor’s initial rotation (which was not 0,0,0) so I’ve come up with a workaround that I don’t think should be necessary.

This code fixes the issue and rotates the locations by the inverse of the actor’s rotation:

// add start control point
	// NOTE: despite bPositionIsRelative=false, actor rotation affects locations.
	// rotating location by inverse of rotation fixes this
	FVector StartFixedLocation = MoveComp->GetOwner()->GetActorQuat().Inverse().RotateVector(MoveComp->GetOwner()->GetActorLocation());
	MoveComp->AddControlPointPosition(StartFixedLocation, false);

// Add target control point
	// again, rotating the target location by actor's inverse rotation because things don't work properly
	FVector TargetFixedLocation = MoveComp->GetOwner()->GetActorQuat().Inverse().RotateVector(Location);
	MoveComp->AddControlPointPosition(TargetFixedLocation, false);

This post was 50% to report what definitely seems like a bug or get confirmation that it is intended, and 50% to help whoever decides to use this under-documented little component in the future. Maybe I was missing some secret function in the component?

I’m using UE4.26.1 and am fixing a handful of bugs before updating to 4.27. I get the feeling this isn’t something that hasn’t been changed but apologies if it has been.

Edit: I checked 4.27 release notes and the only mention of the component was this:

  • Exposed AddControlPointPosition and ResetControlPoints to Blueprint in the InterpToMovementComponent.

So I’m assuming this is either strangely intended, I’ve missed some secret function, or a bug. I’m leaning towards bug.