Setting a Variable in a Niagara Component with C++ in Unreal Engine 5
Let's go over how to set a user param variable for a Niagara component in C++.
Software Versions: Unreal Engine 5.5.1 | Rider 2024.3.2
Project Name: MyProject
When making the Spawn Actors section of the GD Tactics Gym I struggled with updating a variable or value inside a Niagara component. Like most software, things are constantly being iterated on so I looked at a variety of resources and I tried many different things, but eventually landed on the Niagara component's SetVariable<Type>
functions.
First, to enable Niagara in your C++ project you need to enable the plugin and update you project's Build
file, in my case MyProject.Build.cs
. Add Niagara
to the ModuleNames
, link to the project's build file.
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "UMG", "Niagara" });
In my example I'll be updating a MaterialInterface
user parameter variable set inside a Niagara System
. I created a new Niagara System using the ConfettiBurst
template and called it N_ConfettiBurst
.
Inside the N_ConfettiBurst
system I created a new user parameter called MyMaterial
of type Material Interface
. The variable is bound to the sole emitter's Sprite Rendering material. You can actually leave the sprite's base material value empty because the user parameter will override it. By default the MyMaterial
value is set the material M_Solid
, its a very basic material with a vector parameter called Base Color
. The M_Solid
material can be found inside the project's LevelPrototyping/Materials
directory.
Moving to C++. In this example I'll be referring to the project's MySpawnActorProjectile.h
and MySpawnActorProjectile.cpp
files.
Now let's add a NiagaraComponent
to our actor. I added additional UPROPERTY
s for the material I want to update along with a color parameter. These properties will change per your actor's/project's requirements.
MySpawnActorParticle.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MySpawnActorParticle.generated.h"
class UNiagaraComponent;
UCLASS()
class MYPROJECT_API AMySpawnActorParticle : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMySpawnActorParticle();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
UPROPERTY()
USceneComponent* MyRoot;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UNiagaraComponent* MyNiagaraComponent;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UMaterialInterface* MyMaterialInterface;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector ParticleColor;
};
Accessing variables inside a NiagaraComponent
proved to be difficult. I'm still not sure how to GET
a user parameter variable value, it might not be best practice or recommended. I came across multiple approaches of either looping through emitter renderers, grabbing the NiagaraSystem
via the GetAsset
function and parsing it's contents, or even older functions for getting Niagara values, but it seems like these approaches were either deprecated or convoluted. Maybe there will be GETTER
functions added in the future, but it's nothing to worry about.
However, the NiagaraComponent
comes with a lot of great SETTER
functions. The component appears to still be under active development as of recently, so there are some deprecated functions inside the .h
file, which is totally cool, it's fun to see things change. So as of UE 5.5.1, the recommend approach is the use the SetVariable
functions with the FName
variant as mentioned in their code comments.
Inside NiagaraComponent.h
we can see all the setter functions. I'll list some below, but there are many more, you might need get one that fits your param type.
NiagaraComponent.h
...
NIAGARA_API void SetVariableActor(FName InVariableName, ...)
NIAGARA_API void SetVariableBool(FName InVariableName, ...)
NIAGARA_API void SetVariableInt(FName InVariableName, ...)
NIAGARA_API void SetVariableFloat(FName InVariableName, ...)
NIAGARA_API void SetVariableLinearColor(FName InVariableName, ...)
NIAGARA_API void SetVariableMaterial(FName InVariableName, ...)
NIAGARA_API void SetVariableObject(FName InVariableName, ...)
NIAGARA_API void SetVariableVec3(FName InVariableName, ...)
...
Inside MySpawnActorParticle.cpp
we can now use the component's SetVariableMaterial
function with argument FName("MyMaterial")
to successfully set our NiagaraComponent
s user parameter. In this situation I'm creating a MaterialInstanceDynamic
to set the Material
's Base Color
param to the ParticleColor
variable defined earlier. The ParticleColor
variable can be set in a variety of ways, in a future post I'll set the value before the actor is spawned. All the logic in this example is happening inside the BeginPlay
function, adjust as needed.
MySpawnActorParticle.cpp
#include "MySpawnActorParticle.h"
#include "NiagaraComponent.h"
AMySpawnActorParticle::AMySpawnActorParticle()
{
MyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("MyRoot"));
MyRoot->bVisualizeComponent = true;
RootComponent = MyRoot;
MyNiagaraComponent = CreateDefaultSubobject<UNiagaraComponent>(TEXT("MyNiagaraComponent"));
MyNiagaraComponent->SetupAttachment(RootComponent);
ParticleColor = FVector(1.f, 0.f, 0.f);
}
void AMySpawnActorParticle::BeginPlay()
{
Super::BeginPlay();
if (MyMaterialInterface != nullptr)
{
UMaterialInstanceDynamic* MyDynamicMaterialInstance = UMaterialInstanceDynamic::Create(MyMaterialInterface, MyNiagaraComponent);
if (MyDynamicMaterialInstance != nullptr)
{
MyDynamicMaterialInstance->SetVectorParameterValue(FName("Base Color"), ParticleColor);
MyNiagaraComponent->SetVariableMaterial(FName("MyMaterial"), MyDynamicMaterialInstance);
}
}
}
I hope this helps in your game development journey, I definitely struggled with this concept with it for awhile.
Harrison McGuire