Okay I’m done and really happy with the results. I’ll put them here for reference:
First, I use a UCurveFloat in C++ which can be set in blueprint and is used for easing the movement, as discussed before:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
UCurveFloat* EasingCurve;
I also calculated nice tangents which work well for my magic projectiles:
FOccluderVertexArray Points;
Points.Add(Start);
Points.Add(TargetLocation);
FVector Tangent1, Tangent2;
Tangent1 = Tangent2 = TargetLocation - Start;
Tangent1 = Tangent1.RotateAngleAxis(Angle, FVector(0, 0, 1));
Tangent1 *= 2;
Tangent2 = Tangent2.RotateAngleAxis(-Angle, FVector(0, 0, 1));
Tangent2 *= 1;
Spline->SetSplineWorldPoints(Points);
Spline->SetTangentsAtSplinePoint(0, Tangent1, Tangent1, ESplineCoordinateSpace::World);
Spline->SetTangentsAtSplinePoint(1, Tangent2, Tangent2, ESplineCoordinateSpace::World);
TimeTotal = Spline->GetSplineLength() / Speed;
Ticking is almost the same as before:
void AAbilityProjectile::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (IsValid(TargetActor))
{
TargetLocation = TargetActor->GetActorLocation();
Spline->SetLocationAtSplinePoint(1, TargetLocation, ESplineCoordinateSpace::World);
}
TimePassed += DeltaTime;
float Tween = EasingCurve->GetFloatValue(TimePassed / TimeTotal);
float Dist = Tween * Spline->GetSplineLength();
FVector Location = Spline->GetWorldLocationAtDistanceAlongSpline(Dist);
FRotator Rotation = Spline->GetWorldRotationAtDistanceAlongSpline(Dist);
PaperFlipbookComponent->SetWorldLocation(Location);
PaperFlipbookComponent->SetWorldRotation(Rotation + FRotator(0,0,-90));
if (TimePassed >= TimeTotal)
{
if (GetWorld()->IsServer())
{
HandleTargetHit();
}
Destroy();
}
}
TimeTotal is now based on the spline length which means that from my 3 projectiles, the one with Angle == 0 arrives first. Visually that looks a bit odd so I am thinking to base TimeTotal on the length between start and end vector instead of the spline length but that is an easy change.
Thanks again for your inputs!