I’m experimenting with Niagara, hoping to make a damage numbers particle effect that will normally use an all white color curve scaled by a user parameter to indicate the severity of the damage, and when a critical hit occurs it will instead use a rainbow gradient color curve. I couldn’t find a way within Niagara module scripting to conditionally choose one color curve vs. another, and from what I’ve read this is because significant conditional branches have a heavy impact on code intended to run on the GPU (HLSL generated by Niagara).
Instead, I’m trying to set the color curve to use as a Niagara User parameter in C++ and then only the color scale vector changes based on whether or not the damage represents a critical hit (which can be achieved with the selector node). The problem I’m having is that the color curve User parameter is apparently not getting set properly; regardless of the curve I set it to in C++, the particle system uses the default value I provided in the Niagara particle editor for the color curve User parameter. If I unset the default, then the particles become transparent (presumably because the default color curve value is now all zeroes).
Here’s the color curve asset loading code:
FString ColorCurvePath = TEXT("/Game/Ryddelmyst_Assets/Textures/");
if (IsCrit)
{
ColorCurvePath += TEXT("RainbowRoadColorCurve");
}
else
{
ColorCurvePath += TEXT("WhiteColorCurve");
}
UCurveLinearColor* ColorCurveAsset = LoadObject<UCurveLinearColor>
(
nullptr,
*ColorCurvePath,
nullptr,
LOAD_None,
nullptr
);
I wasn’t 100% certain that UCurveLineraColor is the class I want to represent an asset created in the content browser via Right Click → Miscellaneous → Curve → CurveLinearColor, but it looks about right and gives the FRichCurve curve data that UNiagaraDataInterfaceColorCurve seems to want.
I’m trying to set the UNiagaraDataInterfaceColorCurve as follows:
UNiagaraDataInterface* DataInterfaceForDamageColorCurve = UNiagaraFunctionLibrary::GetDataInterface(UNiagaraDataInterface::StaticClass(), FloatingNumbersFX_Component, FName{ TEXT("DamageColorCurve") });
if (DataInterfaceForDamageColorCurve)
{
if (const auto DataInterfaceColorCurve = Cast<UNiagaraDataInterfaceColorCurve>(DataInterfaceForDamageColorCurve))
{
DataInterfaceColorCurve->RedCurve = ColorCurveAsset->FloatCurves[0];
DataInterfaceColorCurve->GreenCurve = ColorCurveAsset->FloatCurves[1];
DataInterfaceColorCurve->BlueCurve = ColorCurveAsset->FloatCurves[2];
DataInterfaceColorCurve->AlphaCurve = ColorCurveAsset->FloatCurves[3];
}
}
I’ve verified that the variable ColorCurveAsset is non-null after load and that its Keys[0].Value and Keys[0].Time match the asset configuration, so presumably the load operation succeeded. The question then is how should I actually set the color channel curves in the UNiagaraDataInterfaceColorCurve object? The best approach I could see from the API was to set each channel curve individually as seen above, which potentially doesn’t work since I’m seeing the default color curve value used at runtime.