
ue-niagara-effects
Use when driving Niagara VFX from C++: spawning a system, overriding User parameters, binding data interfaces, sending gameplay data through Niagara Data Channels, pooling components or handling OnSystemFinished. Also use when the user mentions 'Niagara', 'particle system', 'VFX', 'UNiagaraComponent', 'UNiagaraFunctionLibrary', 'SpawnSystemAtLocation', 'SpawnSystemAttached', 'SetVariableFloat', 'User. parameter', 'data interface', 'ENCPoolMethod', 'sim cache', 'lightweight emitter', 'muzzle flash' or 'impact effect'. For particle materials and dynamic material instances, see ue-materials-rendering; for audio-reactive effects, see ue-audio-system.
- Installs
- 1.2K
- Last 24h
- +15
- Trending rank
- #6956
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-niagara-effects- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads ue-niagara-effects automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
UE Niagara Effects
Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
Niagara ships as the Niagara plugin (Engine/Plugins/FX/Niagara, enabled by default). Game code spawns and drives systems through UNiagaraFunctionLibrary and UNiagaraComponent, feeds them structured data through data interfaces and Niagara Data Channels, and controls cost through component pooling and UNiagaraEffectType scalability. Add "Niagara" to your module's PublicDependencyModuleNames, plus "NiagaraCore" when you subclass UNiagaraDataInterface.
Context
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
| Request is about… | Go to |
|---|---|
| Asset, emitter and component relationships | System and Component Model |
| Firing an effect, attaching a trail | Spawning Systems |
| Activate, reset, pause, seek | Lifecycle Control |
| Pushing floats, colors, vectors into an effect | Setting User Parameters |
| Skeletal/static mesh, curve, array, texture DIs | Data Interfaces |
| Exposing game-specific data to Niagara scripts | Custom Data Interfaces |
| Gameplay events into Niagara, VFX-to-VFX messaging | Niagara Data Channels |
| Knowing when an effect is done | Completion Callbacks |
| Recording and replaying a simulation | Simulation Caches |
| Cheap high-count emitters | Lightweight Emitters |
| Spawn cost, reuse, priming | Component Pooling |
| Culling, tick order, determinism | Scalability and Tick Behavior |
| Build.cs and includes | Build Setup |
System and Component Model
UNiagaraSystem asset; holds TArray<FNiagaraEmitterHandle>
└── FNiagaraEmitterHandle GetEmitterBase() -> UNiagaraEmitterBase
├── UNiagaraEmitter ENiagaraEmitterMode::Standard (stateful, scripted)
└── UNiagaraStatelessEmitter ENiagaraEmitterMode::Stateless (lightweight)
UNiagaraComponent runtime instance; GetSystemInstanceController()
Authors expose parameters to C++ by placing them in the User. namespace in the Niagara editor. Only User.* parameters can be overridden at runtime; System.*, Emitter.*, Particle.* and Module.* are simulation-internal.
Discover what an asset exposes without opening the editor:
#include "NiagaraFunctionLibrary.h"
// FNiagaraUserParameterInfo: ParameterName, ParameterType, TypeName.
const TArray<FNiagaraUserParameterInfo> Params = UNiagaraFunctionLibrary::GetAllUserParameters(ImpactSystem);
// FNiagaraMinimalEmitterInfo: EmitterName, bIsEnabled, bIsLightweight, UsedRendererMaterials, UsedRendererMeshes.
const TArray<FNiagaraMinimalEmitterInfo> Emitters = UNiagaraFunctionLibrary::GetAllEmitters(ImpactSystem);
Spawning Systems
#include "NiagaraComponent.h"
#include "NiagaraFunctionLibrary.h"
// One-shot at a world location. Returns nullptr on dedicated servers and when the
// pre-cull check rejects the spawn, so always null-check.
UNiagaraComponent* ImpactVFX = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
this, // const UObject* WorldContextObject
ImpactSystem, // UNiagaraSystem*
HitLocation, // FVector Location
FRotator::ZeroRotator, // FRotator Rotation
FVector(1.0f), // FVector Scale
/*bAutoDestroy=*/ true,
/*bAutoActivate=*/ true,
ENCPoolMethod::AutoRelease,
/*bPreCullCheck=*/ true);
if (ImpactVFX)
{
ImpactVFX->SetVariableVec3(FName("User.HitNormal"), HitNormal);
ImpactVFX->SetVariableLinearColor(FName("User.HitColor"), DamageColor);
}
Attached, persistent effect. Note the argument order: bAutoDestroy comes before bAutoActivate here.
UNiagaraComponent* TrailVFX = UNiagaraFunctionLibrary::SpawnSystemAttached(
TrailSystem,
WeaponMesh, // USceneComponent* AttachToComponent
FName("MuzzleSocket"), // FName AttachPointName
FVector::ZeroVector,
FRotator::ZeroRotator,
EAttachLocation::SnapToTarget,
/*bAutoDestroy=*/ false,
/*bAutoActivate=*/ true,
ENCPoolMethod::ManualRelease,
/*bPreCullCheck=*/ true);
A second SpawnSystemAttached overload inserts FVector Scale after Rotation and then orders the tail as LocationType, bAutoDestroy, PoolingMethod, bAutoActivate, bPreCullCheck. Pick one overload deliberately; the two are easy to confuse.
SpawnSystemAtLocationWithParams and SpawnSystemAttachedWithParams take a single FFXSystemSpawnParameters struct (Particles/ParticleSystemComponent.h) when you want named fields instead of a long argument list. That struct carries EPSCPoolMethod PoolingMethod, not ENCPoolMethod.
For an effect that repeats on one actor, own the component instead of spawning per event:
// Header:
UPROPERTY(VisibleAnywhere, Category = "VFX")
TObjectPtr<UNiagaraComponent> EngineTrailVFX;
// Constructor:
EngineTrailVFX = CreateDefaultSubobject<UNiagaraComponent>(TEXT("EngineTrailVFX"));
EngineTrailVFX->SetupAttachment(GetRootComponent());
EngineTrailVFX->SetAutoActivate(false);
// Gameplay. SetAsset resets existing override parameters unless you opt out,
// so re-apply User parameters after a swap or pass false.
EngineTrailVFX->SetAsset(BoostTrailSystem, /*bResetExistingOverrideParameters=*/ true);
EngineTrailVFX->Activate(/*bReset=*/ true);
Lifecycle Control
NiagaraComp->Activate(/*bReset=*/ false); // resume
NiagaraComp->Activate(/*bReset=*/ true); // restart from scratch
NiagaraComp->Deactivate(); // stop spawning, let particles drain
NiagaraComp->DeactivateImmediate(); // kill particles now
NiagaraComp->ResetSystem(); // restart from time 0
NiagaraComp->ReinitializeSystem(); // full re-init; more expensive than ResetSystem
NiagaraComp->SetPaused(true);
NiagaraComp->SetAutoDestroy(true);
// Warm-up: advance age before the effect becomes visible.
NiagaraComp->SetDesiredAge(2.5f);
NiagaraComp->SeekToDesiredAge(2.5f);
// Deterministic stepping for cutscenes and tests.
NiagaraComp->AdvanceSimulation(/*TickCount=*/ 30, /*TickDeltaSeconds=*/ 0.0166f);
Setting User Parameters
Setters take an FName including the namespace prefix. They are silent no-ops when the name or the type does not match the asset.
NiagaraComp->SetVariableFloat(FName("User.DamageAmount"), 150.0f);
NiagaraComp->SetVariableInt(FName("User.ProjectileCount"), 12);
NiagaraComp->SetVariableBool(FName("User.bIsCritical"), bIsCriticalHit);
NiagaraComp->SetVariableVec2(FName("User.UVOffset"), FVector2D(0.5, 0.25));
NiagaraComp->SetVariableVec3(FName("User.TargetDirection"), AimDirection);
NiagaraComp->SetVariableVec4(FName("User.CustomData"), FVector4(1.0, 0.5, 0.0, 1.0));
NiagaraComp->SetVariableLinearColor(FName("User.TintColor"), FLinearColor::Red);
NiagaraComp->SetVariableQuat(FName("User.Orientation"), GetActorQuat());
NiagaraComp->SetVariableMatrix(FName("User.LocalToTarget"), TargetMatrix);
// Positions go through the LWC-aware setter, not SetVariableVec3.
NiagaraComp->SetVariablePosition(FName("User.WorldOrigin"), WorldSpaceOrigin);
// Object-valued parameters.
NiagaraComp->SetVariableObject(FName("User.TargetMesh"), TargetMeshComponent);
NiagaraComp->SetVariableActor(FName("User.SourceActor"), this);
NiagaraComp->SetVariableMaterial(FName("User.FXMaterial"), DynamicMaterial);
NiagaraComp->SetVariableStaticMesh(FName("User.ScatterMesh"), ScatterMesh);
NiagaraComp->SetVariableTexture(FName("User.FlowMap"), FlowTexture);
NiagaraComp->SetVariableTextureRenderTarget(FName("User.SceneRT"), SceneRenderTarget);
// Getters report success through an out parameter and are [[nodiscard]].
bool bIsValid = false;
const float CurrentRate = NiagaraComp->GetVariableFloat(FName("User.EmitRate"), bIsValid);
| Namespace prefix | Settable from C++ |
|---|---|
User. | Yes — the only runtime-overridable namespace |
System. | No — engine-owned (Age, DeltaTime, ExecutionState) |
Emitter. | No — per-emitter simulation state |
Particle. | No — per-particle simulation state |
Module. | No — private to a stack node |
Full C++-to-Niagara type table, the array function library matrix and the pool-method values are in niagara-parameter-types.md.
Data Interfaces
Data interfaces are UNiagaraDataInterface subclasses exposed as User.* parameters of DI type. Bind them with the typed helpers in UNiagaraFunctionLibrary, which take the parameter name as const FString&.
UNiagaraFunctionLibrary::OverrideSystemUserVariableSkeletalMeshComponent(
NiagaraComp, TEXT("User.SourceMesh"), GetMesh());
UNiagaraFunctionLibrary::SetSkeletalMeshDataInterfaceFilteredBones(
NiagaraComp, TEXT("User.SourceMesh"), { FName("hand_l"), FName("hand_r") });
UNiagaraFunctionLibrary::SetSkeletalMeshDataInterfaceSamplingRegions(
NiagaraComp, TEXT("User.SourceMesh"), { FName("UpperBody") });
UNiagaraFunctionLibrary::OverrideSystemUserVariableStaticMeshComponent(
NiagaraComp, TEXT("User.ScatterMesh"), ScatterMeshComponent);
UNiagaraFunctionLibrary::SetTextureObject(NiagaraComp, TEXT("User.FlowTexture"), FlowTexture);
Array DIs are the workhorse for pushing gameplay data per frame. These helpers take FName:
#include "NiagaraDataInterfaceArrayFunctionLibrary.h"
TArray<FVector> Waypoints = BuildWaypoints();
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector(
NiagaraComp, FName("User.Waypoints"), Waypoints);
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayFloatValue(
NiagaraComp, FName("User.HeatData"), /*Index=*/ 5, /*Value=*/ 0.9f, /*bSizeToFit=*/ false);
Fetch a DI object when you need to mutate it directly:
#include "NiagaraDataInterfaceCurve.h"
UNiagaraDataInterfaceCurve* CurveDI =
UNiagaraFunctionLibrary::GetDataInterface<UNiagaraDataInterfaceCurve>(
NiagaraComp, FName("User.SpeedCurve"));
if (CurveDI)
{
CurveDI->Curve.Reset();
CurveDI->Curve.AddKey(0.0f, 0.0f);
CurveDI->Curve.AddKey(1.0f, 500.0f);
#if WITH_EDITORONLY_DATA
CurveDI->UpdateLUT(); // editor-only
#endif
// With bUseLUT (default true) CPU and GPU both sample the LUT baked at cook time
// (NiagaraDataInterfaceCurve.cpp:182), so key edits only take effect in cooked builds
// if the DI was authored with bUseLUT off.
}
The non-template overload GetDataInterface(UClass* DIClass, UNiagaraComponent*, FName) covers the case where the class is only known at runtime. The built-in DI catalogue with header paths, properties and sim-target support is in niagara-data-interfaces.md.
Custom Data Interfaces
Subclass UNiagaraDataInterface (NiagaraDataInterface.h). The function list is editor-only data: the override is GetFunctionsInternal(TArray<FNiagaraFunctionSignature>& OutFunctions) const declared inside #if WITH_EDITORONLY_DATA, plus GetVMExternalFunction to bind the CPU implementations and Equals / CopyToInternal so instances compare and duplicate correctly. GPU support adds ProvidePerInstanceDataForRenderThread and PerInstanceDataPassedToRenderThreadSize. Full class template in niagara-data-interfaces.md.
Niagara Data Channels
Data Channels are the supported bridge between gameplay code and Niagara, and between independent systems. A channel is a UNiagaraDataChannelAsset describing a payload; writers publish elements, Niagara emitters and game code read them.
#include "NiagaraDataChannelAccessContext.h"
#include "NiagaraDataChannelAccessor.h"
#include "NiagaraDataChannelAsset.h"
#include "NiagaraDataChannelFunctionLibrary.h"
void AMyProjectile::ReportImpact(const FVector& ImpactPoint, const FVector& ImpactNormal)
{
const FNiagaraDataChannelSearchParameters SearchParams(GetRootComponent());
UNiagaraDataChannelWriter* Writer = UNiagaraDataChannelLibrary::WriteToNiagaraDataChannel(
this,
ImpactChannel, // UPROPERTY() TObjectPtr<UNiagaraDataChannelAsset>
SearchParams,
/*Count=*/ 1,
/*bVisibleToGame=*/ false,
/*bVisibleToCPU=*/ true,
/*bVisibleToGPU=*/ true,
TEXT("MyProjectileImpact"));
if (Writer)
{
Writer->WritePosition(FName("Position"), 0, ImpactPoint);
Writer->WriteVector(FName("Normal"), 0, ImpactNormal);
}
}
Reading back on the game side:
void AMyProjectile::DrainImpacts()
{
const FNiagaraDataChannelSearchParameters SearchParams(GetRootComponent());
UNiagaraDataChannelReader* Reader = UNiagaraDataChannelLibrary::ReadFromNiagaraDataChannel(
this, ImpactChannel, SearchParams, /*bReadPreviousFrame=*/ true);
for (int32 Index = 0; Reader && Index < Reader->Num(); ++Index)
{
bool bValid = false;
const FVector Position = Reader->ReadPosition(FName("Position"), Index, bValid);
if (bValid)
{
SpawnDecalAt(Position);
}
}
}
SubscribeToNiagaraDataChannel(WorldContextObject, Channel, SearchParams, UpdateDelegate, UnsubscribeToken) pushes an FOnNewNiagaraDataChannelPublish callback whenever new elements are published; its FNiagaraDataChannelUpdateContext carries Reader, FirstNewDataIndex, LastNewDataIndex and NewElementCount. Pair every subscription with UnsubscribeFromNiagaraDataChannel using the stored token.
UNiagaraDataChannelLibrary also offers GetDataChannelElementCount, single-element ReadFromNiagaraDataChannelSingle / WriteToNiagaraDataChannelSingle, and _WithContext variants that take an FNDCAccessContextInst instead of FNiagaraDataChannelSearchParameters. The search-parameter overloads are the legacy path and do not support newer channel types; prefer the context variants for new channels.
Completion Callbacks
OnSystemFinished is DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNiagaraSystemFinished, class UNiagaraComponent*, PSystem), so the handler must be a UFUNCTION() declared in a class body.
// MyVFXComponent.h
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "MyVFXComponent.generated.h"
class UNiagaraComponent;
class UNiagaraSystem;
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class MYGAME_API UMyVFXComponent : public UActorComponent
{
GENERATED_BODY()
public:
void PlayBurst(UNiagaraSystem* System, const FVector& Location);
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
protected:
UFUNCTION()
void HandleVFXFinished(UNiagaraComponent* FinishedComponent);
UPROPERTY(Transient)
TObjectPtr<UNiagaraComponent> ActiveVFX;
};
// MyVFXComponent.cpp
#include "MyVFXComponent.h"
#include "NiagaraComponent.h"
#include "NiagaraFunctionLibrary.h"
void UMyVFXComponent::PlayBurst(UNiagaraSystem* System, const FVector& Location)
{
ActiveVFX = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
this, System, Location, FRotator::ZeroRotator, FVector(1.0f),
/*bAutoDestroy=*/ false, /*bAutoActivate=*/ true, ENCPoolMethod::ManualRelease);
if (ActiveVFX)
{
ActiveVFX->OnSystemFinished.AddDynamic(this, &UMyVFXComponent::HandleVFXFinished);
}
}
void UMyVFXComponent::HandleVFXFinished(UNiagaraComponent* FinishedComponent)
{
FinishedComponent->OnSystemFinished.RemoveDynamic(this, &UMyVFXComponent::HandleVFXFinished);
FinishedComponent->ReleaseToPool();
ActiveVFX = nullptr;
}
void UMyVFXComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if (ActiveVFX)
{
ActiveVFX->OnSystemFinished.RemoveDynamic(this, &UMyVFXComponent::HandleVFXFinished);
ActiveVFX->ReleaseToPool(); // ManualRelease components leak unless released
ActiveVFX = nullptr;
}
Super::EndPlay(EndPlayReason);
}
Simulation Caches
A UNiagaraSimCache records simulation frames and plays them back deterministically — useful for cinematics, network-visible hero effects and regression tests.
#include "NiagaraComponent.h"
#include "NiagaraSimCache.h"
#include "NiagaraSimCacheFunctionLibrary.h"
UNiagaraSimCache* Cache = UNiagaraSimCacheFunctionLibrary::CreateNiagaraSimCache(this);
FNiagaraSimCacheCreateParameters CreateParameters;
UNiagaraSimCache* OutCache = nullptr;
UNiagaraSimCacheFunctionLibrary::CaptureNiagaraSimCacheImmediate(
Cache, CreateParameters, NiagaraComp, OutCache,
/*bAdvanceSimulation=*/ false, /*AdvanceDeltaTime=*/ 0.01666f);
// Play a cache back on any component running the same system, then hand control
// back to the live simulation.
NiagaraComp->SetSimCache(Cache, /*bResetSystem=*/ true);
NiagaraComp->ClearSimCache(/*bResetSystem=*/ true);
UNiagaraSimCache exposes IsCacheValid(), CanRead(UNiagaraSystem*), GetNumFrames(), GetStartSeconds() and GetDurationSeconds(). Data interfaces that hold their own state participate through INiagaraSimCacheCustomStorageInterface.
Lightweight Emitters
Emitters come in two modes, reported by FNiagaraEmitterHandle::GetEmitterMode(): ENiagaraEmitterMode::Standard (UNiagaraEmitter, full scripted simulation) and ENiagaraEmitterMode::Stateless (UNiagaraStatelessEmitter, a fixed-cost analytic emitter with no per-particle simulation buffers). Stateless emitters are authored in the Niagara editor and cost far less on CPU and memory; prefer them for ambient, high-instance-count effects.
UNiagaraStatelessEmitter lives in the module-internal Internal/Stateless/NiagaraStatelessEmitter.h, so game modules cannot include it. Drive stateless emitters the same way as any other system — through UNiagaraComponent and User. parameters. To detect them from game code, read bIsLightweight on FNiagaraMinimalEmitterInfo from UNiagaraFunctionLibrary::GetAllEmitters.
Component Pooling
ENCPoolMethod on every spawn call selects pool behavior: None (fresh component), AutoRelease (returned automatically on completion; do not keep the pointer past the spawning tick) and ManualRelease (you call ReleaseToPool()). ManualRelease_OnComplete and FreeInPool are hidden internal states.
#include "NiagaraComponentPool.h"
#include "NiagaraWorldManager.h"
// Prime one world before a gameplay-critical moment. Call the pool directly:
// FNiagaraWorldManager::PrimePool / PrimePoolForAllWorlds are not NIAGARA_API
// (NiagaraWorldManager.h:236-238) and fail to link from a game module.
if (FNiagaraWorldManager* WorldMan = FNiagaraWorldManager::Get(GetWorld()))
{
WorldMan->GetComponentPool()->PrimePool(ExplosionSystem, GetWorld());
}
Pool capacity is a per-system property on the asset (MaxPoolSize, PoolPrimeSize on UFXSystemAsset, Particles/ParticleSystem.h:126,135); priming creates min(PoolPrimeSize, MaxPoolSize) components and PoolPrimeSize defaults to 0, so set it or priming is a no-op (NiagaraComponentPool.cpp:285). Global CVars: FX.NiagaraComponentPool.Enable, FX.NiagaraComponentPool.KillUnusedTime, FX.NiagaraComponentPool.CleanTime, FX.NiagaraComponentPool.Validation.
Scalability and Tick Behavior
NiagaraComp->SetAllowScalability(true); // let the scalability manager cull this instance
NiagaraComp->SetTickBehavior(ENiagaraTickBehavior::UsePrereqs);
ENiagaraTickBehavior | Meaning |
|---|---|
UsePrereqs | Tick after attachment and data-interface prerequisites. Safest, and the default. |
UseComponentTickGroup | Ignore prerequisites; use the component's own tick group. |
ForceTickFirst | Tick in the first tick group. |
ForceTickLast | Tick in the last tick group. |
Scalability lives in the UNiagaraEffectType assigned to the system: SystemScalabilitySettings, EmitterScalabilitySettings, CullReaction, UpdateFrequency and an instanced SignificanceHandler. It is data-driven; no per-platform C++.
CPU vs GPU sim: CPU simulations support every data interface and can be read back; GPU simulations scale to far higher counts but support a narrower DI set and cannot be read back without an explicit readback path.
Determinism: for effects that must match across clients, enable fixed tick on the UNiagaraSystem asset (bFixedTickDelta / FixedTickDeltaTime, readable through HasFixedTickDelta() and GetFixedTickDeltaTime()) and use CPU simulation. Cosmetic effects belong on clients only — guard spawns with IsRunningDedicatedServer().
Occlusion: SetOcclusionQueryMode(ENiagaraOcclusionQueryMode) / GetOcclusionQueryMode() control occlusion queries per component (Default, AlwaysEnabled, AlwaysDisabled).
Niagara Fluids (Beta in 5.8) adds GPU fluid and gas solvers at a high per-frame cost; restrict it to hero effects.
Build Setup
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "Niagara", "NiagaraCore" });
"NiagaraCore" is only needed when you derive from UNiagaraDataInterface. Headers under Internal/ (for example Internal/DataInterface/NiagaraDataInterfaceStaticMesh.h) are not includable from game modules.
Deprecated — do not use
| Do not emit | Use in 5.8 | Source |
|---|---|---|
SetNiagaraVariableFloat(const FString&, float) and every other SetNiagaraVariable* FString setter | SetVariableFloat(FName, float) and the matching SetVariable* FName setters | UE_DEPRECATED(5.3) in Public/NiagaraComponent.h |
UNiagaraDataInterface::GetFunctions(TArray<FNiagaraFunctionSignature>&) | GetFunctionsInternal(TArray<FNiagaraFunctionSignature>&) const inside #if WITH_EDITORONLY_DATA | UE_DEPRECATED(5.4) in Classes/NiagaraDataInterface.h |
UNiagaraDataInterface::RequiresDistanceFieldData() | RequiresGlobalDistanceField() | UE_DEPRECATED(5.4) in Classes/NiagaraDataInterface.h |
UNiagaraDataInterface::ReadsEmitterParticleData(const FString&) | GetEmitterReferencesByName() | UE_DEPRECATED(5.4) in Classes/NiagaraDataInterface.h |
UNiagaraDataInterface::PostCompile() with no arguments | the PostCompile overload taking the owning system | UE_DEPRECATED(5.7) in Classes/NiagaraDataInterface.h |
UNiagaraDataInterface::IsUsedByCPUEmitter() / IsUsedByGPUEmitter() | IsUsedWithCPUScript() / IsUsedWithGPUScript() | UE_DEPRECATED(5.3) in Classes/NiagaraDataInterface.h |
UNiagaraComponent::GetSystemInstance() | GetSystemInstanceController() | UE_DEPRECATED(5.0) in Public/NiagaraComponent.h |
| An abstract or submix-named audio data interface base class | UNiagaraDataInterfaceAudioSpectrum or UNiagaraDataInterfaceAudioOscilloscope, each with a USoundSubmix* Submix property | only three concrete audio DIs exist, in Classes/NiagaraDataInterfaceAudio*.h |
Treating ENCPoolMethod::FreeInPool as a spawn argument | None, AutoRelease or ManualRelease | UMETA(Hidden) in Public/NiagaraComponentPoolMethodEnum.h |
Common Mistakes
Assuming there is no C++ event path into Niagara: there is. Use Data Channels (UNiagaraDataChannelLibrary) for gameplay-to-Niagara events rather than toggling a User. bool and hoping the spawn script samples it on the right tick.
Spawning a component every tick: SpawnSystemAtLocation inside Tick creates and destroys a component per frame. Create the component once, or spawn with ENCPoolMethod::AutoRelease on discrete events only.
Wrong namespace or wrong type: SetVariableFloat(FName("Emitter.Speed"), 300.f) and SetVariableVec3 on a Color parameter both fail silently. The author must expose the value as User.Speed, the setter must match the authored type, and world positions go through SetVariablePosition so LWC is handled.
Ignoring the return value of a spawn call: it is nullptr on dedicated servers and when the pre-cull check rejects the spawn. Null-check before touching the component.
UFUNCTION() on an out-of-line definition: the macro only has meaning inside a UCLASS body. A OnSystemFinished handler marked UFUNCTION() above its .cpp definition will not bind; declare it in the header as shown above.
Holding a pointer to an AutoRelease component: the pool reclaims it as soon as the system completes, and later access is unsafe. Use ManualRelease plus ReleaseToPool() when you need a lasting handle.
Treating a data interface like a component: UpdateLUT() is WITH_EDITORONLY_DATA and must be guarded, and MarkRenderStateDirty() does not exist — UNiagaraDataInterface derives from UObject. Array changes are picked up on the next simulation tick; curve key changes only if the curve DI has bUseLUT off.
Related Skills
ue-materials-rendering— particle materials, dynamic material instances, render targets fed to DIsue-actor-component-architecture— component creation, attachment, activation and lifecycleue-animation-system— skeletal mesh sockets, notifies and bone data that drive mesh-sampling DIsue-gameplay-abilities— GameplayCue-driven effect spawning and ability-scoped VFX ownershipue-audio-system— sound submixes and spectrum analysis behind the audio data interfacesue-async-threading— render-thread and task-graph rules when feeding DIs from background workue-procedural-generation— generating the point and spline data that array and spline DIs consumeue-sequencer-cinematics— Level Sequences, playback, cine cameras and Movie Render Graph
FAQ
What does the ue-niagara-effects skill do?
Use when driving Niagara VFX from C++: spawning a system, overriding User parameters, binding data interfaces, sending gameplay data through Niagara Data Channels, pooling components or handling OnSystemFinished. Also use when the user mentions 'Niagara', 'particle system', 'VFX', 'UNiagaraComponent', 'UNiagaraFunctionLibrary', 'SpawnSystemAtLocation', 'SpawnSystemAttached', 'SetVariableFloat', 'User. parameter', 'data interface', 'ENCPoolMethod', 'sim cache', 'lightweight emitter', 'muzzle flash' or 'impact effect'. For particle materials and dynamic material instances, see ue-materials-rendering; for audio-reactive effects, see ue-audio-system.
How do I install ue-niagara-effects?
Run npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-niagara-effects in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/ue-niagara-effects/ (personal) or .claude/skills/ue-niagara-effects/ (project).
Which AI agents can use ue-niagara-effects?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is ue-niagara-effects safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains ue-niagara-effects?
It is published by quodsoler in quodsoler/unreal-engine-skills. It has 1,224 recorded installs.
More from quodsoler/unreal-engine-skills
ue-cpp-foundations
quodsoler/unreal-engine-skills
Use when writing Unreal Engine C++ that touches the reflection system or core types: UCLASS, UPROPERTY, UFUNCTION, USTRUCT, UENUM, GENERATEDBODY, TObjectPtr, TWeakObjectPtr, TSharedPtr, FGCObject, TArray, TMap, TSet, TOptional, TVariant, DECLAREDYNAMICMULTICASTDELEGATE, AddDynamic, FName, FString, FText, UGameInstanceSubsystem, UWorldSubsystem, GetDefault, TNotNull. Also use when the user mentions 'UE C++', 'garbage collection', 'CDO', 'smart pointers' or 'specifiers'. For Actor and component lifecycle, see ue-actor-component-architecture; for Build.cs and modules, see ue-module-build-system; for Blueprint-facing functions and latent actions, see ue-blueprint-cpp-interop.
ue-ui-umg-slate
quodsoler/unreal-engine-skills
Use when writing or fixing Unreal Engine UI in C++ — UMG user widgets, Slate widgets, Common UI screens, or MVVM view models. Also use when the user mentions 'UUserWidget', 'NativeConstruct', 'BindWidget', 'CreateWidget', 'AddToViewport', 'ESlateVisibility', 'OnClicked', 'UListView', 'widget animation', 'SNew', 'SLATEBEGINARGS', 'SCompoundWidget', 'UCommonActivatableWidget', 'activatable widget stack', 'UCommonButtonBase', 'gamepad focus', 'FUIInputConfig', 'UMVVMViewModelBase', 'FieldNotify', or 'WidgetComponent'. For input modes and Enhanced Input, see ue-input-system; for Slate in editor tooling, see ue-editor-tools.
ue-editor-tools
quodsoler/unreal-engine-skills
Use when extending the Unreal Editor from C++ with detail customizations, editor utility widgets, menus, editor modes, asset definitions or editor subsystems. Also use when the user mentions 'IDetailCustomization', 'IPropertyTypeCustomization', 'CustomizeDetails', 'RegisterCustomClassLayout', 'IDetailLayoutBuilder', 'AddCustomRow', 'IPropertyHandle', 'UToolMenus', 'ExtendMenu', 'FToolMenuEntry', 'UEditorUtilityWidget', 'Blutility', 'UAssetActionUtility', 'UEditorSubsystem', 'UEdMode', 'UAssetDefinition', 'UFactory', 'FScopedTransaction', or 'editor module'. For Slate fundamentals, see ue-ui-umg-slate; for Build.cs wiring, see ue-module-build-system.
ue-project-context
quodsoler/unreal-engine-skills
Use when creating, refreshing or repairing .agents/ue-project-context.md, the project document every other UE skill reads first. Also use when the user says 'project context', 'set up context', 'UE context', 'scan my project', 'onboard the agent to my project', 'update project context', 'configure project', 'what engine version is this project on', 'which plugins do we have enabled', or complains that UE advice keeps coming out generic. For Build.cs and Target.cs mechanics, see ue-module-build-system; for naming and API-macro conventions, see ue-cpp-foundations; for GAS specifics, see ue-gameplay-abilities.
ue-testing-debugging
quodsoler/unreal-engine-skills
Use when writing or running Unreal Engine tests, adding logging, or profiling a build. Also use when the user mentions 'UELOG', 'log category', 'DEFINELOGCATEGORY', 'UELOGFMT', 'verbosity', 'check', 'ensure', 'ensureMsgf', 'verify', 'IMPLEMENTSIMPLEAUTOMATIONTEST', 'automation test', 'TESTCLASS', 'CQTest', 'AFunctionalTest', 'latent command', 'Unreal Insights', 'TRACECPUPROFILEREVENTSCOPE', 'TRACEBOOKMARK', 'stat unit', 'SCOPECYCLECOUNTER', 'memreport', 'DrawDebugLine', 'UEVLOG', 'gameplay debugger', 'ShowDebug', 'console command', 'CVar', or 'why is my frame time bad'. For module and target wiring, see ue-module-build-system; for editor tooling, see ue-editor-tools.
ue-module-build-system
quodsoler/unreal-engine-skills
Use when writing or fixing Build.cs, Target.cs, .uproject or .uplugin files, creating a module or plugin, or resolving an Unreal build error. Also use when the user mentions 'unresolved external symbol', 'LNK2019', 'cannot open include file', 'C1083', 'MODULENAMEAPI', 'PublicDependencyModuleNames', 'IWYU', 'PCHUsage', 'IMPLEMENTMODULE', 'IMPLEMENTPRIMARYGAMEMODULE', 'LoadingPhase', 'circular dependency', 'Missing precompiled manifest', 'EngineAssociation', 'IncludeOrderVersion', 'Live Coding'. For UCLASS/UPROPERTY rules see ue-cpp-foundations; for editor modules see ue-editor-tools; for Game Feature plugins see ue-game-features.
Popular media & creative skills
hyperframes
heygen-com/hyperframes
Read first to make, edit, animate or render any video with HyperFrames (HTML rendered to video), including launch films, explainers, music videos, charts, maps, vertical clips, title cards, captions and overlays. Holds the render contract, the work loop and what each kind of video needs.
media-use
heygen-com/hyperframes
Get or make any media for a HyperFrames video - music, sound effects, images, icons, logos, voiceover, avatar and generated video, transcripts, cutouts, colour grades and looks - with HeyGen or free local tools, and mix placed audio. Also for footage that looks dark, flat or dull, or should be stylized or hidden.
hyperframes-registry
heygen-com/hyperframes
About 450 ready-made HyperFrames blocks and components installed as editable source - transitions, overlays, titles, kinetic type, captions, charts, map overlays, 3D, camera moves. Use it before hand-building any named visual (CRT scanlines, glitch, film grain, a chart); also for hyperframes add and catalog.
hyperframes-creative
heygen-com/hyperframes
Non-animation creative direction for HyperFrames videos. Use for design spec (frame.md / design.md) handling, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns, and brand / style decisions. For atomic motion patterns and scene blueprints, use hyperframes-animation.
ai-video-generation
101-skills/superpowers
Generate AI videos with Google Veo, Seedance 2.0, HappyHorse, Wan, Grok and 40+ models via inference.sh CLI. Models: Veo 3.1, Veo 3, Seedance 2.0, HappyHorse 1.0, Wan 2.5, Grok Imagine Video, OmniHuman, Fabric, HunyuanVideo. Capabilities: text-to-video, image-to-video, reference-to-video, video editing, lipsync, avatar animation, video upscaling, foley sound. Use for: social media videos, marketing content, explainer videos, product demos, AI avatars. Triggers: video generation, ai video, text to video, image to video, veo, animate image, video from image, ai animation, video generator, generate video, t2v, i2v, ai video maker, create video with ai, runway alternative, pika alternative, sora alternative, kling alternative, seedance, happyhorse
ai-image-generation
101-skills/superpowers
Generate AI images with GPT-Image-2, FLUX, Gemini, Grok, Seedream, Reve and 50+ models via inference.sh CLI. Models: GPT-Image-2, FLUX Dev LoRA, FLUX.2 Klein LoRA, Gemini 3 Pro Image, Grok Imagine, Seedream 4.5, Reve, ImagineArt. Capabilities: text-to-image, image-to-image, inpainting, LoRA, image editing, upscaling, text rendering. Use for: AI art, product mockups, concept art, social media graphics, marketing visuals, illustrations. Triggers: flux, image generation, ai image, text to image, stable diffusion, generate image, ai art, midjourney alternative, dall-e alternative, text2img, t2i, image generator, ai picture, create image with ai, generative ai, ai illustration, grok image, gemini image, gpt image, openai image, chatgpt image