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?
eldany.uy
(eldany.uy)
November 16, 2023, 7:58pm
2
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 )
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.
eldany.uy
(eldany.uy)
November 16, 2023, 8:15pm
4
here is source code…maybe you can make your own function
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);
}
eldany.uy
(eldany.uy)
November 16, 2023, 8:25pm
5
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
system
(system)
Closed
December 16, 2023, 11:38pm
8
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.