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++.

Unreal Engine 5 Niagara editor basic confetti burst template with MyMaterial user param
Confetti burst Niagara template

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.

Unreal Engine 5 editor Niagara System new template ConfettiBurst
Niagara System 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.

Unreal Engine 5 N_ConfettiBurst Niagara System with user param MyMaterial highlighted sections
N_ConfettiBurst MyMaterial binding
Unreal Engine 5 M_Solid material with Base Color vector parameter
M_Solid Material

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 UPROPERTYs 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 NiagaraComponents 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.

Loading...