Agent skill

Ue Niagara Effects

by quodsoler in quodsoler/unreal-engine-skills

A skill your agent uses when driving Niagara VFX from C++: spawning a system, overriding User parameters, binding data interfaces, sending gameplay data through Niagara Data Channels, pooling…

MITAuto-check passedGame Development

Install Ue Niagara Effects

skills CLI
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effects --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-niagara-effects .claude/skills/ue-niagara-effects && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ue-niagara-effects
GitHub stars
362
Token cost
~6.7k tokens
SKILL.md length
1,535 words
Files
3 (incl. references)
Skills in repo
31
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when driving Niagara VFX from C++: spawning a system, overriding User parameters, binding data interfaces, sending gameplay data through Niagara Data Channels, pooling…

  • Driving Niagara VFX from C++: spawning a system
  • SKILL.md covers Context, System and Component Model, Spawning Systems and Lifecycle Control, plus 13 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Overriding User parameters

What it does

Ue Niagara Effects is an agent skill from quodsoler/unreal-engine-skills. 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…

Its SKILL.md is about 6.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including reference files (for example `references/niagara-data-interfaces.md` and `references/niagara-parameter-types.md`).

It sits in Game Development. It works with C++. The repository describes itself as: Unreal Engine C++ skills for AI coding agents. 27 skills covering gameplay, rendering, networking, animation, and more. Works with Claude Code, Cursor, Windsurf, and any agent… The licence is MIT.

When your agent uses it

  • Driving Niagara VFX from C++: spawning a system
  • Overriding User parameters
  • Binding data interfaces
  • Sending gameplay data through Niagara Data Channels

Example prompts

  • “Niagara”
  • “particle system”
  • “UNiagaraComponent”
  • “/ue-niagara-effects”

What it can do on your machine

Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp and csharp).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ue Niagara Effects loads about 6.7k tokens when it runs, and up to ~14k if it reads all its reference files. Until then it costs about 168 tokens; SKILL.md has 1,535 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~168
When it runs · the whole SKILL.md, loaded when a task matches
~6.7k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~14k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 1,535 words, ~6,744 tokens.

Download SKILL.mdSave it as .claude/skills/ue-niagara-effects/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
ue-niagara-effects
description
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.
metadata.version
2.0.0
metadata.engine
5.8

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 relationshipsSystem and Component Model
Firing an effect, attaching a trailSpawning Systems
Activate, reset, pause, seekLifecycle Control
Pushing floats, colors, vectors into an effectSetting User Parameters
Skeletal/static mesh, curve, array, texture DIsData Interfaces
Exposing game-specific data to Niagara scriptsCustom Data Interfaces
Gameplay events into Niagara, VFX-to-VFX messagingNiagara Data Channels
Knowing when an effect is doneCompletion Callbacks
Recording and replaying a simulationSimulation Caches
Cheap high-count emittersLightweight Emitters
Spawn cost, reuse, primingComponent Pooling
Culling, tick order, determinismScalability and Tick Behavior
Build.cs and includesBuild 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:

cpp
#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

cpp
#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.

cpp
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:

cpp
// 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

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

cpp
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 prefixSettable 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&.

cpp
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:

cpp
#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:

cpp
#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.

cpp
#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:

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

cpp
// 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;
};
cpp
// 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.

cpp
#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.

cpp
#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.

Show full SKILL.md (635 more words)Show less

Scalability and Tick Behavior

cpp
NiagaraComp->SetAllowScalability(true);    // let the scalability manager cull this instance
NiagaraComp->SetTickBehavior(ENiagaraTickBehavior::UsePrereqs);
ENiagaraTickBehaviorMeaning
UsePrereqsTick after attachment and data-interface prerequisites. Safest, and the default.
UseComponentTickGroupIgnore prerequisites; use the component's own tick group.
ForceTickFirstTick in the first tick group.
ForceTickLastTick 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

csharp
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 emitUse in 5.8Source
SetNiagaraVariableFloat(const FString&, float) and every other SetNiagaraVariable* FString setterSetVariableFloat(FName, float) and the matching SetVariable* FName settersUE_DEPRECATED(5.3) in Public/NiagaraComponent.h
UNiagaraDataInterface::GetFunctions(TArray<FNiagaraFunctionSignature>&)GetFunctionsInternal(TArray<FNiagaraFunctionSignature>&) const inside #if WITH_EDITORONLY_DATAUE_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 argumentsthe PostCompile overload taking the owning systemUE_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 classUNiagaraDataInterfaceAudioSpectrum or UNiagaraDataInterfaceAudioOscilloscope, each with a USoundSubmix* Submix propertyonly three concrete audio DIs exist, in Classes/NiagaraDataInterfaceAudio*.h
Treating ENCPoolMethod::FreeInPool as a spawn argumentNone, AutoRelease or ManualReleaseUMETA(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.

  • ue-materials-rendering — particle materials, dynamic material instances, render targets fed to DIs
  • ue-actor-component-architecture — component creation, attachment, activation and lifecycle
  • ue-animation-system — skeletal mesh sockets, notifies and bone data that drive mesh-sampling DIs
  • ue-gameplay-abilities — GameplayCue-driven effect spawning and ability-scoped VFX ownership
  • ue-audio-system — sound submixes and spectrum analysis behind the audio data interfaces
  • ue-async-threading — render-thread and task-graph rules when feeding DIs from background work
  • ue-procedural-generation — generating the point and spline data that array and spline DIs consume
  • ue-sequencer-cinematics — Level Sequences, playback, cine cameras and Movie Render Graph

© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (references) in skills/ue-niagara-effects of quodsoler/unreal-engine-skills.

  • SKILL.md
  • references/niagara-data-interfaces.md
  • references/niagara-parameter-types.md

Open the folder on GitHubat commit f3742d7

Compare with similar skills

Ue Niagara Effects next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Ue Niagara Effects compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ue Niagara Effects this skillquodsoler/unreal-engine-skills362—~6.7kAutomated safety check: PassMIT
Ue Specifiersfjz13/UnrealSpecifiers1.1k—~1.4kAutomated safety check: PassCustom licence
Validate GsdkPlayFab/gsdk170—~645Automated safety check: PassApache-2.0
Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin338—~1.8kAutomated safety check: PassMIT
Sokol Netelix22/Sokol.NET154—~2.8kAutomated safety check: PassMIT
Gdextension Hygienemicrosoft/XBOX-Godot-Sample237—~983Automated safety check: PassMIT

Similar skills

  • Ue Specifiers

    fjz13/UnrealSpecifiers

    A skill your agent uses when writing, editing, reviewing, validating, or explaining Unreal Engine C++ reflected declarations: UCLASS, USTRUCT, UENUM, UINTERFACE, UPROPERTY, UFUNCTION, UPARAM, UMETA…

    1.1k GitHub stars~1.4k tokensUpdated 4 mo ago
    Game DevelopmentAuto-check passed
  • Validate Gsdk

    PlayFab/gsdk

    Validates PlayFab Game Server SDK (GSDK) integrations in game server projects.

    170 GitHub stars~645 tokensUpdated 2 days ago
    Game DevelopmentAuto-check passed
  • Unreal Engine MCP

    EpicGames/unreal-engine-skills-for-claude-code-plugin

    Drives a live Unreal Editor through the unreal-mcp server: spawn actors, edit Blueprints, materials and sequences, change properties and trigger Live Coding.

    338 GitHub stars~1.8k tokensUpdated 24 days ago
    Game DevelopmentAuto-check passed
  • Sokol Net

    elix22/Sokol.NET

    Sokol.NET framework development — use for ANY work in this repo: creating or debugging examples, building/running for desktop/Android/iOS/Web, writing or compiling shaders, adding a new C/C++…

    154 GitHub stars~2.8k tokensUpdated yesterday
    Game DevelopmentAuto-check passed
  • Gdextension Hygiene

    microsoft/XBOX-Godot-Sample

    Official

    Run a Godot/GDExtension finish pass over the current diff: enforce headless GDScript validation, public API docclasses coverage, docs/spec/sample/test synchronization, and registration or CMake…

    237 GitHub stars~983 tokensUpdated 3 days ago
    Game DevelopmentAuto-check passed
  • Intrinsic Core Solution Building

    intrinsic-ai/intrinsic-core

    Intrinsic Solution Building Library (SBL) Python SDK guide for connecting to workcells, composing Behavior Trees, querying/mutating ObjectWorld frames, binding equipment resources, and orchestrating…

    562 GitHub stars~2.7k tokensUpdated today
    Game DevelopmentAuto-check passed

More from quodsoler/unreal-engine-skills

All 31 skills in this repo
  • Unreal Actor-Component Architecture

    quodsoler/unreal-engine-skills

    Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.

    362 GitHub stars~7.5k tokensUpdated 12 days ago
    Auto-check passed
  • Unreal Engine AI and Navigation

    quodsoler/unreal-engine-skills

    Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.

    362 GitHub stars~8.9k tokensUpdated 12 days ago
    Auto-check passed
  • Unreal Engine Animation System

    quodsoler/unreal-engine-skills

    Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.

    362 GitHub stars~7k tokensUpdated 12 days ago
    Auto-check passed
  • Unreal Engine Async and Threading

    quodsoler/unreal-engine-skills

    Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.

    362 GitHub stars~8k tokensUpdated 12 days ago
    Auto-check passed
  • Ue Audio System

    quodsoler/unreal-engine-skills

    A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.

    362 GitHub stars~7.9k tokensUpdated 12 days ago
    Auto-check passed
  • Unreal Blueprint and C++ Interop

    quodsoler/unreal-engine-skills

    Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.

    362 GitHub stars~7.8k tokensUpdated 12 days ago
    Auto-check passed

Works with

Questions about Ue Niagara Effects

What does Ue Niagara Effects do?

A skill your agent uses when driving Niagara VFX from C++: spawning a system, overriding User parameters, binding data interfaces, sending gameplay data through Niagara Data Channels, pooling…. Ue Niagara Effects is an agent skill from quodsoler/unreal-engine-skills. 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.

When should I use Ue Niagara Effects?

Ue Niagara Effects fits situations like: driving Niagara VFX from C++: spawning a system; overriding User parameters; binding data interfaces; sending gameplay data through Niagara Data Channels.

How do I install Ue Niagara Effects in Claude Code?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a claude-code`. Or copy the skill folder (skills/ue-niagara-effects in quodsoler/unreal-engine-skills) into .claude/skills/ue-niagara-effects in your project. Claude Code loads it when a task matches its description.

How do I install Ue Niagara Effects in Codex?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a codex`. Or copy the skill folder (skills/ue-niagara-effects in quodsoler/unreal-engine-skills) into .agents/skills/ue-niagara-effects in your project. Codex loads it when a task matches its description.

Can I use Ue Niagara Effects in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-niagara-effects, .gemini/skills/ue-niagara-effects, .github/skills/ue-niagara-effects and .opencode/skills/ue-niagara-effects in your project.

What does Ue Niagara Effects need to run?

SKILL.md names no scripts, command-line tools or credentials: Ue Niagara Effects is instructions for the agent only.

Does Ue Niagara Effects access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Ue Niagara Effects safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Ue Niagara Effects use?

Ue Niagara Effects is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ue Niagara Effects use?

About 6.7k tokens (SKILL.md is roughly 27k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 7.3k tokens, read only when the agent opens those files.

What are the alternatives to Ue Niagara Effects?

Skills that share tags, products or a category with Ue Niagara Effects: Ue Specifiers (fjz13/UnrealSpecifiers, 1.1k stars), Validate Gsdk (PlayFab/gsdk, 170 stars), Unreal Engine MCP (EpicGames/unreal-engine-skills-for-claude-code-plugin, 338 stars) and Sokol Net (elix22/Sokol.NET, 154 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Ue Niagara Effects?

quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 362 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.

Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.