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…
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…
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effects --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ 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-srcUse ~/.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/
Install the "ue-niagara-effects" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effects into .claude/skills/ue-niagara-effects/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-niagara-effects", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effectsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effects --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/ue-niagara-effects .agents/skills/ue-niagara-effects && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ue-niagara-effects" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effects into .agents/skills/ue-niagara-effects/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-niagara-effects", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effects --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/ue-niagara-effects .cursor/skills/ue-niagara-effects && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ue-niagara-effects" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effects into .cursor/skills/ue-niagara-effects/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-niagara-effects", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/quodsoler/unreal-engine-skills.git --path skills/ue-niagara-effects--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effects --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/ue-niagara-effects .gemini/skills/ue-niagara-effects && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ue-niagara-effects" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effects into .gemini/skills/ue-niagara-effects/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-niagara-effects", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effectsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/ue-niagara-effects .github/skills/ue-niagara-effects && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ue-niagara-effects" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effects into .github/skills/ue-niagara-effects/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-niagara-effects", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-niagara-effects -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-niagara-effects --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/ue-niagara-effects .opencode/skills/ue-niagara-effects && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ue-niagara-effects" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-niagara-effects into .opencode/skills/ue-niagara-effects/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-niagara-effects", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ue-niagara-effectsA 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. 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.
Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.
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.
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.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
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.
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.
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.
The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 1,535 words, ~6,744 tokens.
.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.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.
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 |
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);#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);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);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 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.
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.
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.
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);
}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.
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.
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.
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.
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.
| 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 |
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 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© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (references) in skills/ue-niagara-effects of quodsoler/unreal-engine-skills.
Open the folder on GitHubat commit f3742d7
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Ue Niagara Effects this skillquodsoler/unreal-engine-skills | 362 | — | ~6.7k | Automated safety check: Pass | MIT | |
| Ue Specifiersfjz13/UnrealSpecifiers | 1.1k | — | ~1.4k | Automated safety check: Pass | Custom licence | |
| Validate GsdkPlayFab/gsdk | 170 | — | ~645 | Automated safety check: Pass | Apache-2.0 | |
| Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin | 338 | — | ~1.8k | Automated safety check: Pass | MIT | |
| Sokol Netelix22/Sokol.NET | 154 | — | ~2.8k | Automated safety check: Pass | MIT | |
| Gdextension Hygienemicrosoft/XBOX-Godot-Sample | 237 | — | ~983 | Automated safety check: Pass | MIT |
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…
PlayFab/gsdk
Validates PlayFab Game Server SDK (GSDK) integrations in game server projects.
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.
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++…
microsoft/XBOX-Godot-Sample
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…
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…
quodsoler/unreal-engine-skills
Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.
quodsoler/unreal-engine-skills
Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.
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.
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.
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.
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.
Works with
Categories
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.
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.
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.
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.
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.
SKILL.md names no scripts, command-line tools or credentials: Ue Niagara Effects is instructions for the agent only.
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.
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.
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.
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.
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.
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.