Creating and using UCurveFloat in Unreal Engine in C++ for FTimeline

I don’t understand how I can create an object of the UCurveFloat class in C++ to pass it to the AddInterpFloat function.
In .h:

UFUNCTION()
void ProgressInTimeline(float val);

In .cpp:

FTimeline TimelineRecoil;
FOnTimelineFloat ProgressInTimelineFunction;

ProgressInTimelineFunction.BindUFunction(this, TEXT("ProgressInTimeline"));

TimelineRecoil.AddInterpFloat(???Curve???, ProgressInTimelineFunction);
TimelineRecoil.SetTimelineLengthMode(TL_LastKeyFrame);
        
TimelineRecoil.PlayFromStart();

Yes, I can reference an existing UCurveFloat instance using the editor,

UPROPERTY()
UCurveFloat* Curve;

but I’d like to create it manually. I found the FRuntimeFloatCurve struct, but it seems that with it I can only get the curve in the FRichCurve struct, but the AddInterpFloat function requires a UCurveFloat object. In the FRuntimeFloatCurve structure, there is a reference to an ExternalCurve of type UCurveFloat, but I did not understand if this makes sense to me.

Have you tried this ?

#include "Curves/CurveFloat.h"

UCurveFloat* Curve = NewObject<UCurveFloat>(this);
Curve->FloatCurve.UpdateOrAddKey(0.f, 0.f);
Curve->FloatCurve.UpdateOrAddKey(1.f, 1.f);
TimelineRecoil.AddInterpFloat(Curve, ProgressInTimelineFunction);
2 Likes

Yes thank you

UCurveFloat* Curve = NewObject<UCurveFloat>();
FKeyHandle KeyHandle = Curve.AddKey(0.0f, 0.1f);
RealCurve.SetKeyInterpMode(KeyHandle, RCIM_Linear);

The SetKeyInterpMode function uses ERichCurveInterpMode, but the blueprints seem to use EInterpCurveMode, no?

Screenshots:

UE4Editor_ioyOmSgePy

I am trying to do the same in c++ code.

How to adjust the smoothness of curves using tangents? I see SetKeyTangentMode and SetKeyTangentWeightMode, but I don’t really understand how to use it to manually set the tangents for the points so that the offset of the curves is what I want to do.

Well you can either use automatic tangents :

FKeyHandle KeyHandle = Curve->FloatCurve.AddKey(0.0f, 0.1f);
Curve->FloatCurve.SetKeyInterpMode(KeyHandle, ERichCurveInterpMode::RCIM_Cubic, /*auto*/true);

Or get the key from key handle to fill values manually :

FKeyHandle KeyHandle = Curve->FloatCurve.AddKey(0.0f, 0.1f);
FRichCurveKey& Key = Curve->FloatCurve.GetKey(KeyHandle);
Key.InterpMode = ERichCurveInterpMode::RCIM_Cubic;
Key.ArriveTangent = 1.f;
Key.LeaveTangent = 1.f;
1 Like

Hi. I tried this solution but my timeline calls “ProgressInTimeline” only (exactly) once, despite having it defined as:

UCurveFloat* Curve = NewObject<UCurveFloat>(this);
FKeyHandle KeyHandle = Curve->FloatCurve.UpdateOrAddKey(0.f, 0.f);
Curve->FloatCurve.UpdateOrAddKey(1.f, 1.f);
Curve->FloatCurve.SetKeyInterpMode(KeyHandle, ERichCurveInterpMode::RCIM_Cubic, /*auto*/true);