How do you set a Texture on a Niagara variable at runtime?

How do you set a texture variable on a Niagara system at runtime? In BP, I see only the following data types. I have also looked into Niagara Parameter Collections, and you can create a texture property in the PC, but similarly you can’t set it at runtime in BP. Is there something I am missing?

286719-niagara.png

It looks like it can be done, but only with custom C++ code. Basically the texture sampling code is exposed to niagara through the UNiagaraDataInterfaceTexture. It contains a reference to the UTexture* property. You’ll need to get a handle on your Niagara Component, and access its OverrideParameters property. You can then construct an instance of UNiagaraDataInterfaceTexture and call OverrideParameters.SetParameterValue with it.

That seems to be the theory at least. Haven’t done it yet but it looks straightforward.

Hi, I needed it so I ended up with this code in my project source

#include "NiagaraComponent.h"
#include "NiagaraUserRedirectionParameterStore.h"
#include "NiagaraDataInterfaceTexture.h"

UFUNCTION(BlueprintPure, Category = Niagara, meta = (DisplayName = "Set Niagara Variable (UTexture)"))
void UMyBlueprintFunctionLibrary::SetNiagaraVariableTexture(const class UNiagaraComponent* niagara, const FString& InVariableName, UTexture* InValue)
{
	if (!niagara || !InValue) return;

	FName VarName = FName(*InVariableName);

	FNiagaraUserRedirectionParameterStore& overrideParameters = (FNiagaraUserRedirectionParameterStore&)niagara->GetOverrideParameters();
	
	UNiagaraDataInterfaceTexture* data = (UNiagaraDataInterfaceTexture*)overrideParameters.GetDataInterface(FNiagaraVariable(FNiagaraTypeDefinition(UNiagaraDataInterfaceTexture::StaticClass()), VarName));
	
	if (data) 
		data->Texture = InValue;
}

Good work @Joti. Seems straightforward enough…makes me wonder why it isn’t in Niagara core :shrug:

This stopped working for me in 4.23 so I looked into it and ended up with this

UFUNCTION(BlueprintPure, Category = Niagara, meta = (DisplayName = "Set Niagara Variable (UTexture)"))
void UHTMLBlueprintFunctionLibrary::SetNiagaraVariableTexture(class UNiagaraComponent* niagara, const FString& InVariableName, UTexture* InValue)
{
	if (!niagara || !InValue) return;

	FName VarName = FName(*InVariableName);

	FNiagaraUserRedirectionParameterStore& overrideParameters = niagara->GetOverrideParameters();
	FNiagaraVariable niagaraVar = FNiagaraVariable(FNiagaraTypeDefinition(UNiagaraDataInterfaceTexture::StaticClass()), VarName);
	UNiagaraDataInterfaceTexture* current = (UNiagaraDataInterfaceTexture*)overrideParameters.GetDataInterface(niagaraVar);

	UNiagaraDataInterfaceTexture* data = NewObject<UNiagaraDataInterfaceTexture>();
	data->Texture = InValue;
	data->CopyTo(current);
	
}

Feels wrong and I’m sure it is but it works for now.

Hey, sorry for replying over a year later.
Your implementation works for me, but only in Editor. But in a Packaged Build, GetOverrideParameters() always returns an FNiagaraParameterStore without any entries.
Do you have any idea what could be causing this? Do you remember if you got this to work in a build?
Edit: I still use 4.23.

Did you find any solution to this Rami?

Unfortunately, I wasn’t able to set a texture. But I did a very elaborate work-around. Was very specific for my usecase, but it might help you.
In UE 4.24 you can set a MaterialInterface as parameter. I created a Material with a Texture parameter, create a MaterialInstanceDynamic (MID) on run time, set the Texture Parameter, and then give the MID to the particles.
I tested this in Packaged Builds and it works.
UE 4.24 just tends to crash if your particles are simulated on the GPU, so watch out.

Thank you Rami, I will give it a try!

Having the same problem and im trying your solution (on 4.24), but i can’t figure out how to pass the MID to the particles at runtime. The niagara UI doesn’t seem to have any option for changing the renderer material by variable, how do you do this?

Originally, I did it in Blueprint but I forgot what exactly that node was called. In C++, the UNiagaraComponent Class has a Function called SetVariableMaterial(FString MaterialName, UMaterialInstanceDynamic* MID).
My ParticleSystem has a User Parameter called Mat, so in my code I wrote
MyNiagaraComponent->SetVariableMaterial(“User.Mat”, MyMatInstance);

hello,call reset system on niagara component will make set txeture object function work!

I eventually figured this out and also got it working for packaged games since the other solution doesn’t work for them.

This is also much simpler. Tested and works on 4.24’s niagara. It gives you the fully dynamic render target->niagara data transfer I was looking for with sending a texture to niagara.

void UMyStaticLibrary::SetNiagaraVariableTexture(UNiagaraComponent* niagara, const FString& InVariableName, UTexture* InValue)
{
	if (!niagara || !InValue) return;

	FName VarName = FName(*InVariableName);

	UNiagaraDataInterface* datainterface = niagara->GetDataInterface(InVariableName);

	if (!datainterface) return;
		
	UNiagaraDataInterfaceTexture* current = Cast<UNiagaraDataInterfaceTexture>(datainterface);
	if (current) {
		UNiagaraDataInterfaceTexture* data = NewObject<UNiagaraDataInterfaceTexture>();
		if (data) {
			data->Texture = InValue;
			data->CopyTo(current);
		}
	}

}

Hey, i eventually figured out the proper solution that also works for packaged games after modifying the other code in this thread. Using a material instance wouldnt work at all for me since im using the texture input to send a render target that’s encoding a ton of array data.

Not sure if you need this but it’s posted as an answer to this question.

Hey Matt, thank you very much for letting me know!