TInterpTo_Constant()?

Hello. I thought someone would have posted about this but cannot find anything on YT, google, or on this forum so posting a new thread.

I am moving an object around with code with the handy function TInterpTo())

const FTransform NextTransform = UKismetMathLibrary::TInterpTo(
		CurrentTransform,
		TargetTransform,
		DeltaTime,
		ScreenInterpSpeed);

	//Set world transform of screenmesh to NextTransform
	ScreenMesh->SetWorldTransform(NextTransform);

This is great but the issue is I want to have it move linearly as opposed to ease-in, ease-out. There are functions VInterpTo_Constant and RInterpTo_Constant etc but not one for TInterpTo.

I tried using those two independently like this:

const FVector NextLocation = UKismetMathLibrary::VInterpTo_Constant(
		CurrentLocation,
			TargetTransform.GetLocation(),
			DeltaTime,
			ScreenInterpSpeed);

	const FRotator NextRotation = UKismetMathLibrary::RInterpTo_Constant(
			CurrentRotation,
			TargetTransform.GetRotation().Rotator(),
			DeltaTime,
			ScreenInterpSpeed);

ScreenMesh->SetWorldLocationAndRotation(NextLocation, NextRotation);

But the result is that the rotation moves much faster than location because they’re receiving the same value for speed. TInterpTo solves this issue but it does not have the Constant version.

Can anyone tell me how to implement this myself?

What you want is LERP (linear interpolation)

FTransform transA,transB;
float alpha;

UKismetMathLibrary::TLerp(transA,transB,alpha);

Just must handle alpha somehow (a timeline handler or whatever :slight_smile: )

I found TLerp in TInterpTo().

const FTransform NextTransform = UKismetMathLibrary::TLerp(CurrentTransform, TargetTransform, ScreenInterpSpeed * DeltaTime);

Only difference is I didn’t clamp the Alpha before, but I am still getting the same issue.

here is source code…maybe you can make your own function :slight_smile:

FTransform UKismetMathLibrary::TInterpTo(const FTransform& Current, const FTransform& Target, float DeltaTime, float InterpSpeed)
{
	if (InterpSpeed <= 0.f)
	{
		return Target;
	}

	const float Alpha = FClamp(DeltaTime * InterpSpeed, 0.f, 1.f);

	return TLerp(Current, Target, Alpha);
}

I think you looking for is more like this:

some custom event that you feed with transform A and B and just store the results somewhere with linear interpolation in a specified time.

source code just in case:

void UKismetSystemLibrary::MoveComponentTo(USceneComponent* Component, FVector TargetRelativeLocation, FRotator TargetRelativeRotation, bool bEaseOut, bool bEaseIn, float OverTime, bool bForceShortestRotationPath, TEnumAsByte<EMoveComponentAction::Type> MoveAction, FLatentActionInfo LatentInfo)
{
	if (UWorld* World = GEngine->GetWorldFromContextObject(Component, EGetWorldErrorMode::LogAndReturnNull))
	{
		FLatentActionManager& LatentActionManager = World->GetLatentActionManager();
		FInterpolateComponentToAction* Action = LatentActionManager.FindExistingAction<FInterpolateComponentToAction>(LatentInfo.CallbackTarget, LatentInfo.UUID);

		const FVector ComponentLocation = (Component != NULL) ? Component->GetRelativeLocation() : FVector::ZeroVector;
		const FRotator ComponentRotation = (Component != NULL) ? Component->GetRelativeRotation() : FRotator::ZeroRotator;

		// If not currently running
		if (Action == NULL)
		{
			if (MoveAction == EMoveComponentAction::Move)
			{
				// Only act on a 'move' input if not running
				Action = new FInterpolateComponentToAction(OverTime, LatentInfo, Component, bEaseOut, bEaseIn, bForceShortestRotationPath);

				Action->TargetLocation = TargetRelativeLocation;
				Action->TargetRotation = TargetRelativeRotation;

				Action->InitialLocation = ComponentLocation;
				Action->InitialRotation = ComponentRotation;

				LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, Action);
			}
		}
		else
		{
			if (MoveAction == EMoveComponentAction::Move)
			{
				// A 'Move' action while moving restarts interpolation
				Action->TotalTime = OverTime;
				Action->TimeElapsed = 0.f;

				Action->TargetLocation = TargetRelativeLocation;
				Action->TargetRotation = TargetRelativeRotation;

				Action->InitialLocation = ComponentLocation;
				Action->InitialRotation = ComponentRotation;
			}
			else if (MoveAction == EMoveComponentAction::Stop)
			{
				// 'Stop' just stops the interpolation where it is
				Action->bInterpolating = false;
			}
			else if (MoveAction == EMoveComponentAction::Return)
			{
				// Return moves back to the beginning
				Action->TotalTime = Action->TimeElapsed;
				Action->TimeElapsed = 0.f;

				// Set our target to be our initial, and set the new initial to be the current position
				Action->TargetLocation = Action->InitialLocation;
				Action->TargetRotation = Action->InitialRotation;

				Action->InitialLocation = ComponentLocation;
				Action->InitialRotation = ComponentRotation;
			}
		}
	}
}

Here is the solution I found here.

FTransform NextTransform;
	
	if (TimeElapsed < ScreenInterpSpeed)
	{
		NextTransform = UKismetMathLibrary::TLerp(StartTransform, TargetTransform, TimeElapsed / LerpDuration);
		ScreenMesh->SetWorldTransform(NextTransform);
		TimeElapsed += DeltaTime;
	}

@eldany.uy many thanks for your help !

1 Like

Glad you solved it!

Dany

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.