Debugging Code
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
A skill your agent uses when writing or debugging Mass Entity ECS code in Unreal Engine C++ — processors, queries, fragments, tags, observers, traits, spawning and large-scale agent simulation.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-mass-entity -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-mass-entity --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-mass-entity .claude/skills/ue-mass-entity && 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-mass-entity" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-mass-entity into .claude/skills/ue-mass-entity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-mass-entity", 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-mass-entityType 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-mass-entity -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-mass-entity --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-mass-entity .agents/skills/ue-mass-entity && 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-mass-entity" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-mass-entity into .agents/skills/ue-mass-entity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-mass-entity", 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-mass-entity -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-mass-entity --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-mass-entity .cursor/skills/ue-mass-entity && 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-mass-entity" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-mass-entity into .cursor/skills/ue-mass-entity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-mass-entity", 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-mass-entity--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-mass-entity -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-mass-entity --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-mass-entity .gemini/skills/ue-mass-entity && 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-mass-entity" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-mass-entity into .gemini/skills/ue-mass-entity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-mass-entity", 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-mass-entityInstalls 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-mass-entity -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-mass-entity .github/skills/ue-mass-entity && 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-mass-entity" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-mass-entity into .github/skills/ue-mass-entity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-mass-entity", 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-mass-entity -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-mass-entity --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-mass-entity .opencode/skills/ue-mass-entity && 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-mass-entity" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-mass-entity into .opencode/skills/ue-mass-entity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-mass-entity", 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-mass-entityA skill your agent uses when writing or debugging Mass Entity ECS code in Unreal Engine C++ — processors, queries, fragments, tags, observers, traits, spawning and large-scale agent simulation.
Ue Mass Entity is an agent skill from quodsoler/unreal-engine-skills. Use when writing or debugging Mass Entity ECS code in Unreal Engine C++ — processors, queries, fragments, tags, observers, traits, spawning and large-scale agent simulation. Also use when the user mentions 'MassEntity', 'UMassProcessor', 'FMassEntityQuery', 'ForEachEntityChunk', 'FMassEntityManager', 'FMassFragment', 'FMassTag', 'FTransformFragment', 'UMassObserverProcessor', 'ObservedTypes', 'Defer', 'archetype', 'AMassSpawner', 'entity config asset', 'MassCrowd', 'ISM crowd', 'entity relations', or 'thousands…
Its SKILL.md is about 7.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/mass-entity-patterns.md` and `references/mass-fragment-reference.md`).
It sits in Game Development. It works with C++ and Unreal Engine. 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 cs).
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 Mass Entity loads about 7.7k tokens when it runs, and up to ~15k if it reads all its reference files. Until then it costs about 176 tokens; SKILL.md has 1,974 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,974 words, ~7,667 tokens.
.claude/skills/ue-mass-entity/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".
Mass is an archetype Entity Component System for simulating thousands of agents with cache-friendly data layouts and multi-threaded processors. The core lives in the always-available runtime modules MassEntity and MassCore (plus MassSignals, MassEngine); gameplay-facing pieces (spawning, representation, movement, LOD, replication, actor bridging) come from the MassGameplay (Experimental in 5.8) plugin, and navigation/behavior from MassAI (Experimental in 5.8) and MassCrowd (Experimental in 5.8).
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 |
|---|---|
| Build.cs, includes, "enable the plugin" | Modules and Build.cs |
| Declaring fragments, tags, shared/chunk data | Fragments, Tags and Archetypes |
| Creating/destroying entities, direct mutation | FMassEntityManager |
| Writing a processor, scheduling, phases | UMassProcessor |
| Selecting entities, requirements, filtering | FMassEntityQuery |
| Reading/writing fragment data in a loop | Iteration and FMassExecutionContext |
| Adding/removing fragments during iteration | Deferred Commands |
| Reacting to fragment/tag add or remove | UMassObserverProcessor |
| One entity outside a processor, fluent build | Single-Entity Access and FEntityBuilder |
| Parent/child links, archetype grouping | Relations and Archetype Groups |
Traits, config assets, AMassSpawner | Traits, Config Assets and Spawning |
| ISM rendering, LOD, actor promotion | Representation and LOD |
| Crowds, lanes, entity AI | Crowd, Navigation and Behavior |
Longer templates live in mass-entity-patterns.md; built-in types and fields in mass-fragment-reference.md.
There is no MassEntity plugin to enable. MassEntity and MassCore are runtime modules that ship with the engine — add them to Build.cs and they link. Only the gameplay layers are plugins, and those must be enabled in the .uproject.
PublicDependencyModuleNames.AddRange(new string[] {
"Core", "CoreUObject", "Engine",
"MassEntity", // manager, processors, queries, commands, relations
"MassCore", // FMassFragment/FMassTag bases, FTransformFragment, traits
"MassSignals", // UMassSignalSubsystem, UMassSignalProcessorBase
"MassCommon", // UE::Mass::ProcessorGroupNames (MassGameplay)
"MassSpawner", // UMassEntityTraitBase, AMassSpawner (MassGameplay)
"MassMovement", // FMassVelocityFragment (MassGameplay)
"MassRepresentation", // ISM visualization + LOD (MassGameplay)
"MassActors", // UMassAgentComponent, actor bridging (MassGameplay)
"MassNavigation", // FMassMoveTargetFragment (MassAI)
});Include paths that moved into MassCore are namespaced under Mass/: Mass/EntityElementTypes.h, Mass/EntityFragments.h, Mass/EntityHandle.h, Mass/ExternalSubsystemTraits.h, Mass/ArchetypeGroup.h. MassEntityTypes.h still pulls the element bases in transitively; prefer the explicit Mass/ path.
| Concept | Base / type | Purpose |
|---|---|---|
| Entity | FMassEntityHandle | Index + SerialNumber identity handle |
| Fragment | FMassFragment | Per-entity mutable data |
| Sparse fragment | FMassSparseFragment | Per-entity data stored outside the archetype (no entity move on add) |
| Tag | FMassTag | Zero-size marker used for filtering |
| Sparse tag | FMassSparseTag | Marker added/removed without an archetype change |
| Chunk fragment | FMassChunkFragment | One instance per memory chunk |
| Shared fragment | FMassSharedFragment | Mutable value shared by entities that reference it |
| Const shared fragment | FMassConstSharedFragment | Immutable shared configuration |
| Archetype | FMassArchetypeHandle | A unique fragment/tag composition |
All of these derive from FMassElement and are declared in Mass/EntityElementTypes.h.
// MyMassTypes.h
#pragma once
#include "Mass/EntityElementTypes.h"
#include "MyMassTypes.generated.h"
USTRUCT()
struct FMyHealthFragment : public FMassFragment
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, Category = "Mass")
float Current = 100.f;
UPROPERTY(EditAnywhere, Category = "Mass")
float Max = 100.f;
};
USTRUCT()
struct FMyAliveTag : public FMassTag { GENERATED_BODY() };
USTRUCT()
struct FMyDeadTag : public FMassTag { GENERATED_BODY() };
USTRUCT()
struct FMySquadSharedFragment : public FMassSharedFragment
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, Category = "Mass")
int32 SquadID = 0;
};Entities with the same composition share an archetype, and each fragment type is stored contiguously per chunk. Adding or removing a fragment or tag moves the entity to another archetype — that is why structural change is deferred during iteration. Sparse fragments and sparse tags exist precisely to avoid that move.
FMassEntityManager is not a UObject; it is a struct deriving from TSharedFromThis<FMassEntityManager> and FGCObject. Reach it through UMassEntitySubsystem (a UMassSubsystemBase, itself a UWorldSubsystem) or through UE::Mass::Utils.
#include "MassEntitySubsystem.h"
#include "MassEntityManager.h"
UMassEntitySubsystem* MassSubsystem = GetWorld()->GetSubsystem<UMassEntitySubsystem>();
FMassEntityManager& EntityManager = MassSubsystem->GetMutableEntityManager();
// const access: MassSubsystem->GetEntityManager()
// free function: UE::Mass::Utils::GetEntityManagerChecked(*GetWorld())FMassEntityHandle Entity = EntityManager.CreateEntity(ArchetypeHandle);
FMassEntityHandle Reserved = EntityManager.ReserveEntity();
EntityManager.BuildEntity(Reserved, ArchetypeHandle);
// Batch creation: hold the returned context until observers should fire.
TArray<FMassEntityHandle> Entities;
TSharedRef<FMassEntityManager::FEntityCreationContext> CreationContext =
EntityManager.BatchCreateEntities(ArchetypeHandle, 5000, Entities);
EntityManager.DestroyEntity(Entity);
EntityManager.BatchDestroyEntities(Entities);FMassEntityHandle::IsSet() (and its alias IsValid()) only reports that Index and SerialNumber are non-zero. To ask whether an entity really exists, use the manager:
EntityManager.IsEntityValid(Handle); // handle refers to a live entity
EntityManager.IsEntityBuilt(Handle); // reserved handle has been built
EntityManager.IsEntityActive(Handle); // valid and builtOutside processor iteration, direct structural mutation is legal. The add/tag/swap calls take TNotNull<const UScriptStruct*> (RemoveFragmentFromEntity still takes a plain const UScriptStruct*, MassEntityManager.h:430), so pass T::StaticStruct() and never a possibly-null pointer.
EntityManager.AddFragmentToEntity(Handle, FMyHealthFragment::StaticStruct());
EntityManager.RemoveFragmentFromEntity(Handle, FMyHealthFragment::StaticStruct());
EntityManager.AddTagToEntity(Handle, FMyDeadTag::StaticStruct());
EntityManager.RemoveTagFromEntity(Handle, FMyDeadTag::StaticStruct());
EntityManager.SwapTagsForEntity(Handle, FMyAliveTag::StaticStruct(), FMyDeadTag::StaticStruct());Entity storage is concurrent: FMassEntityManager::Initialize(const FMassEntityManagerStorageInitParams&) takes FMassEntityManager_InitParams_Concurrent (MaxEntityCount, MaxEntitiesPerPage) and builds a FConcurrentEntityStorage. The subsystem does this for you; only standalone managers need the call.
Subclass UMassProcessor, construct the query with *this so it registers itself, and override the two virtuals exactly as declared.
// MyMovementProcessor.h
#pragma once
#include "MassProcessor.h"
#include "MassEntityQuery.h"
#include "MyMovementProcessor.generated.h"
UCLASS()
class MYGAME_API UMyMovementProcessor : public UMassProcessor
{
GENERATED_BODY()
public:
UMyMovementProcessor();
protected:
virtual void ConfigureQueries(const TSharedRef<FMassEntityManager>& EntityManager) override;
virtual void Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context) override;
private:
FMassEntityQuery MovementQuery;
};// MyMovementProcessor.cpp
#include "MyMovementProcessor.h"
#include "MassCommonTypes.h" // UE::Mass::ProcessorGroupNames
#include "MassExecutionContext.h"
#include "MassMovementFragments.h" // FMassVelocityFragment, FMassMovementParameters
#include "MassSignalSubsystem.h"
#include "Mass/EntityFragments.h" // FTransformFragment
#include "MyMassTypes.h" // FMyHealthFragment, FMyDeadTag, FMySquadSharedFragment
UMyMovementProcessor::UMyMovementProcessor()
: MovementQuery(*this)
{
ProcessingPhase = EMassProcessingPhase::PrePhysics;
ExecutionFlags = static_cast<int32>(EProcessorExecutionFlags::AllNetModes);
ExecutionOrder.ExecuteInGroup = UE::Mass::ProcessorGroupNames::Movement;
ExecutionOrder.ExecuteAfter.Add(TEXT("MassApplyMovementProcessor")); // class FName: no U prefix
bRequiresGameThreadExecution = false;
}EMassProcessingPhase: PrePhysics, StartPhysics, DuringPhysics, EndPhysics, PostPhysics, FrameEnd, MAX.
EProcessorExecutionFlags: None, Standalone, Server, Client, Editor, EditorWorld, AllNetModes (Standalone|Server|Client), AllWorldModes (AllNetModes|EditorWorld), All.
FMassProcessorExecutionOrder carries ExecuteInGroup (an FName) plus ExecuteBefore and ExecuteAfter arrays of processor or group names. A processor's name is its class FName without the U prefix (MassProcessorDependencySolver.cpp:560) — prefer UOther::StaticClass()->GetFName(); a mistyped name just becomes a dummy node with a Log-verbosity message (:705), so the ordering is silently lost. Named groups come from UE::Mass::ProcessorGroupNames: UpdateWorldFromMass, SyncWorldToMass, Behavior, Tasks, Avoidance, ApplyForces, Movement.
Declare requirements in ConfigureQueries — never in the constructor, because the query is bound to the entity manager just before ConfigureQueries runs. Queries built with FMassEntityQuery(UMassProcessor& Owner) are already registered; a default-constructed member still needs RegisterQuery(Query).
void UMyMovementProcessor::ConfigureQueries(const TSharedRef<FMassEntityManager>& EntityManager)
{
MovementQuery.AddRequirement<FTransformFragment>(
EMassFragmentAccess::ReadWrite, EMassFragmentPresence::All);
MovementQuery.AddRequirement<FMassVelocityFragment>(
EMassFragmentAccess::ReadOnly, EMassFragmentPresence::All);
MovementQuery.AddRequirement<FMyHealthFragment>(
EMassFragmentAccess::ReadOnly, EMassFragmentPresence::Optional);
MovementQuery.AddTagRequirement<FMyDeadTag>(EMassFragmentPresence::None);
MovementQuery.AddSharedRequirement<FMySquadSharedFragment>(
EMassFragmentAccess::ReadOnly, EMassFragmentPresence::All);
MovementQuery.AddConstSharedRequirement<FMassMovementParameters>(
EMassFragmentPresence::All);
MovementQuery.AddSubsystemRequirement<UMassSignalSubsystem>(
EMassFragmentAccess::ReadWrite);
}EMassFragmentAccess | Meaning |
|---|---|
None | Filter only, no data binding |
ReadOnly | Read through GetFragmentView<T>() (TConstArrayView) |
ReadWrite | Read/write through GetMutableFragmentView<T>() (TArrayView) |
EMassFragmentPresence | Meaning |
|---|---|
All | Every listed element must be present |
Any | At least one Any-marked element must be present |
None | The element must be absent |
Optional | Bound when present, skipped when absent |
AddChunkRequirement<T>(Access, Presence) binds a FMassChunkFragment. SetChunkFilter(const FMassChunkConditionFunction&) takes a TFunction<bool(const FMassExecutionContext&)> evaluated once per chunk, so the predicate may read chunk fragments, shared fragments and constant data — never per-entity fragments.
void UMyMovementProcessor::Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context)
{
MovementQuery.ForEachEntityChunk(Context, [](FMassExecutionContext& Context)
{
const int32 NumEntities = Context.GetNumEntities();
const TArrayView<FTransformFragment> Transforms = Context.GetMutableFragmentView<FTransformFragment>();
const TConstArrayView<FMassVelocityFragment> Velocities = Context.GetFragmentView<FMassVelocityFragment>();
const float DeltaTime = Context.GetDeltaTimeSeconds();
for (int32 Index = 0; Index < NumEntities; ++Index)
{
Transforms[Index].GetMutableTransform().AddToTranslation(Velocities[Index].Value * DeltaTime);
}
});
}The lambda takes only FMassExecutionContext&; there is no entity-manager parameter. Other accessors: GetEntities() (TConstArrayView<FMassEntityHandle>), GetFragmentView<T>(), GetMutableFragmentView<T>(), GetChunkFragment<T>(), GetConstSharedFragment<T>(), GetMutableSharedFragment<T>(), GetSubsystem<T>(), GetMutableSubsystem<T>() and Defer().
Parallel: ParallelForEachEntityChunk(Context, Lambda, FMassEntityQuery::EParallelExecutionFlags::Default); the nested enum's flags are Default, Force and AutoBalance (MassEntityQuery.h:67).
Time-slicing: ForEachEntityChunk(Context, Limiter, Lambda) takes a UE::Mass::FExecutionLimiter& built from an entity count, stops once that many entities have been visited (always finishing the current chunk) and resumes from the stored position on the next call. Keep the limiter alive across frames as a processor member — a fresh one restarts from the beginning, and the limiter does not notice entities created or destroyed between calls.
Inside ForEachEntityChunk never mutate composition through the entity manager: the entity moves archetype and the views you are holding dangle. Queue the change on Context.Defer().
MovementQuery.ForEachEntityChunk(Context, [](FMassExecutionContext& Context)
{
const TConstArrayView<FMassEntityHandle> Entities = Context.GetEntities();
const TConstArrayView<FMyHealthFragment> Healths = Context.GetFragmentView<FMyHealthFragment>();
for (int32 Index = 0; Index < Context.GetNumEntities(); ++Index)
{
if (Healths[Index].Current <= 0.f)
{
Context.Defer().SwapTags<FMyAliveTag, FMyDeadTag>(Entities[Index]);
Context.Defer().RemoveFragment<FMyHealthFragment>(Entities[Index]);
}
}
});Convenience calls on FMassCommandBuffer: AddFragment<T>, RemoveFragment<T>, AddTag<T>, RemoveTag<T>, SwapTags<TOld, TNew>, AddElements<T...>, RemoveElements<T...>, DestroyEntity, DestroyEntities. The add/remove helpers forward to FMassCommandAddElements<T...> / FMassCommandRemoveElements<T...>, which handle any mix of fragments and tags in a single entity move (SwapTags uses FMassCommandSwapTagsInternal, MassCommandBuffer.h:264).
To add a fragment and its value, push the command type directly:
Context.Defer().PushCommand<FMassCommandAddFragmentInstances<FMyHealthFragment>>(
Entities[Index], FMyHealthFragment{});For arbitrary deferred work push a lambda through FMassDeferredCommand<OpType>: Context.Defer().PushCommand<FMassDeferredSetCommand>([Entity](FMassEntityManager& Manager) { ... }); (aliases FMassDeferredCreate/Add/Remove/ChangeComposition/Set/DestroyCommand, MassCommands.h:1686-1744). For a reusable typed command, subclass FMassBatchedCommand, override Run(FMassEntityManager&) (the const Execute is UE_DEPRECATED(5.7), MassCommands.h:202) and call PushUniqueCommand(TUniquePtr<FMassBatchedCommand>&&).
Commands flush by EMassCommandOperationType bucket, not enum order: Create → Add → ChangeComposition → Set → Remove and Destroy (one shared bucket, push order) → the unclassified None last (MassCommandBuffer.cpp:110-119). That ordering guarantees entities exist before they are modified and fragments exist before values are written.
Observers run when an observed fragment or tag is added or removed. Fill ObservedTypes (an array — one observer can watch several types) and ObservedOperations.
// MyHealthObserver.cpp
UMyHealthObserver::UMyHealthObserver()
: ObserverQuery(*this)
{
ObservedTypes.Add(FMyHealthFragment::StaticStruct());
ObservedOperations = EMassObservedOperationFlags::Add;
}EMassObservedOperationFlags: None, AddElement, RemoveElement, CreateEntity, DestroyEntity, plus the composites Add (= AddElement | CreateEntity), Remove (= RemoveElement | DestroyEntity) and All. Use Add/Remove unless you deliberately want to ignore entity creation — AddElement alone does not fire for entities that are born with the fragment.
Override Register() to customise which types get registered, and read them back with GetObservedTypes() or GetSingleObservedTypeChecked(). Full observer template in mass-entity-patterns.md.
FMassEntityView gives typed access to one entity. It is transient — archetype memory relocates, so build a fresh view every time and never cache one.
if (EntityManager.IsEntityValid(Handle))
{
FMassEntityView View(EntityManager, Handle);
if (FMyHealthFragment* Health = View.GetFragmentDataPtr<FMyHealthFragment>())
{
Health->Current -= Damage;
}
const bool bDead = View.HasTag<FMyDeadTag>();
}UE::Mass::FEntityBuilder (MassEntityBuilder.h) composes an entity fluently and commits once, which beats repeated AddFragmentToEntity calls.
#include "MassEntityBuilder.h"
UE::Mass::FEntityBuilder Builder(EntityManager);
Builder.Add<FTransformFragment>(SpawnTransform);
Builder.Add<FMyHealthFragment>();
Builder.Add<FMyAliveTag>();
FMyHealthFragment& Health = Builder.GetOrCreate<FMyHealthFragment>();
Health.Current = 50.f;
const FMassEntityHandle NewEntity = Builder.Commit();SetForceDeferredCommit(true) routes the commit through the command buffer; CommitAndReprepare() reuses the builder for the next entity.
Relations model typed links between entities. A relation type derives from FMassRelation (itself an FMassTag); the engine ships FMassChildOfRelation with FMassChildOfFragment in Relations/MassChildOf.h. Instances are created and queried through UE::Mass::FRelationManager, reached with EntityManager.GetRelationManager().
#include "MassRelationManager.h"
#include "Relations/MassChildOf.h"
UE::Mass::FRelationManager& Relations = EntityManager.GetRelationManager();
Relations.CreateRelationInstance<FMassChildOfRelation>(ChildEntity, ParentEntity);
TArray<FMassEntityHandle> Children = Relations.GetRelationSubjects(
FMassChildOfRelation::StaticStruct(), ParentEntity);Deferred equivalent: Context.Defer().PushCommand<FMassCommandMakeRelation<FMassChildOfRelation>>(ChildEntity, ParentEntity). Builders take AddRelation<T>(OtherEntity).
Archetype groups let a query process archetypes in a controlled order. EntityManager.FindOrAddArchetypeGroupType(GroupName) returns a UE::Mass::FArchetypeGroupType; EntityManager.BatchGroupEntities(UE::Mass::FArchetypeGroupHandle(GroupType, UE::Mass::FArchetypeGroupID(N)), Entities) assigns entities (Mass/ArchetypeGroup.h:100); Query.GroupBy(GroupType) (optionally with a sort predicate) makes iteration walk groups together.
UMassEntityConfigAsset (a UDataAsset) holds a list of traits that build an entity template. Traits subclass UMassEntityTraitBase and implement BuildTemplate; both virtuals are const and ValidateTemplate takes three parameters.
// MyHealthTrait.h
#pragma once
#include "MassEntityTraitBase.h"
#include "MyHealthTrait.generated.h"
UCLASS(meta = (DisplayName = "My Health"))
class MYGAME_API UMyHealthTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = "Health")
float DefaultHealth = 100.f;
protected:
virtual void BuildTemplate(FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override;
virtual bool ValidateTemplate(const FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World,
FAdditionalTraitRequirements& OutTraitRequirements) const override;
};FMassEntityTemplateBuildContext (declared in MassEntityTemplateRegistry.h) offers AddFragment<T>(), AddFragment_GetRef<T>(), AddTag<T>(), AddChunkFragment<T>(), AddSharedFragment(const FSharedStruct&), AddConstSharedFragment(const FConstSharedStruct&) and AddTranslator<T>().
UMassAssortedFragmentsTrait (MassAssortedFragmentsTrait.h) adds an editor-authored list of fragments and tags without any C++. AMassSpawner references config assets through EntityTypes and drives Count, DoSpawning() and DoDespawning().
UMassRepresentationSubsystem pools Instanced Static Mesh components and spawned actors so thousands of entities render without one actor each.
EMassRepresentationType | Use |
|---|---|
HighResSpawnedActor | Full actor, closest entities |
LowResSpawnedActor | Cheap actor at medium range |
SkinnedMeshInstance | Instanced skinned mesh |
StaticMeshInstance | ISM, the bulk of the crowd |
None | Not rendered |
EMassLOD::Type is High, Medium, Low, Off, Max, stored as TEnumAsByte<EMassLOD::Type>; visibility is EMassVisibility (CanBeSeen, CulledByFrustum, CulledByDistance, Max). UMassMovableVisualizationTrait and UMassStationaryVisualizationTrait configure meshes, actor classes and LOD distances.
Thread-safety for anything a query touches is declared through traits in Mass/ExternalSubsystemTraits.h. TMassExternalSubsystemTraits defaults GameThreadOnly = true; TMassSharedFragmentTraits defaults GameThreadOnly = false. TMassFragmentTraits has no threading flag — only AuthorAcceptsItsNotTriviallyCopyable = false (Mass/ExternalSubsystemTraits.h:57-66). Specialise only when the default is wrong:
template<>
struct TMassExternalSubsystemTraits<UMyMassSubsystem> final
{
enum
{
GameThreadOnly = false,
ThreadSafeWrite = false
};
};UMassCrowdSubsystem (MassCrowd, Experimental in 5.8) tracks ZoneGraph lane occupancy, density and waiting slots. Entities carry FMassCrowdTag and FMassCrowdLaneTrackingFragment; UMassCrowdMemberTrait wires them up. The subsystem specialises TMassExternalSubsystemTraits<UMassCrowdSubsystem> with GameThreadOnly = false, so parallel processors may declare it via AddSubsystemRequirement.
Movement targets live in FMassMoveTargetFragment (MassNavigationFragments.h, module MassNavigation). ZoneGraph itself and Smart Objects are covered by ue-ai-navigation.
Entity behavior runs on State Trees: UMassStateTreeTrait attaches the asset, UMassStateTreeProcessor derives from UMassSignalProcessorBase and ticks only signalled entities, and FMassStateTreeSharedFragment is a const shared fragment. Signal an entity with UMassSignalSubsystem::SignalEntity(FName SignalName, FMassEntityHandle Entity) — signal name first. Task and evaluator authoring belongs to ue-state-trees.
| Do not emit | Use in 5.8 | Source |
|---|---|---|
ObservedType = T::StaticStruct(); | ObservedTypes.Add(T::StaticStruct()); | UE_DEPRECATED(5.8) in MassObserverProcessor.h |
Operation = EMassObservedOperation::AddElement; | ObservedOperations = EMassObservedOperationFlags::Add; | UE_DEPRECATED(5.7) in MassObserverProcessor.h |
GetObservedTypeChecked() | GetSingleObservedTypeChecked() | UE_DEPRECATED(5.8) in MassObserverProcessor.h |
virtual void ConfigureQueries() | ConfigureQueries(const TSharedRef<FMassEntityManager>&) | UE_DEPRECATED(5.6) in MassProcessor.h |
virtual void Initialize(UObject&) | InitializeInternal(UObject&, const TSharedRef<FMassEntityManager>&) | UE_DEPRECATED(5.6) in MassProcessor.h |
ForEachEntityChunk(EntityManager, Context, Fn) | ForEachEntityChunk(Context, Fn) | UE_DEPRECATED(5.6) in MassEntityQuery.h |
ParallelForEachEntityChunk(EntityManager, …), EParallelForMode | ParallelForEachEntityChunk(Context, Fn, EParallelExecutionFlags) | UE_DEPRECATED(5.6) in MassEntityQuery.h |
FMassEntityQuery Query{ FMyFragment::StaticStruct() }; | FMassEntityQuery Query{*this}; + requirements in ConfigureQueries | UE_DEPRECATED(5.6) in MassEntityQuery.h |
Defer().AddTag_RuntimeCheck<T>() and the other *_RuntimeCheck calls | Defer().AddTag<T>(), AddFragment<T>(), RemoveFragment<T>(), RemoveTag<T>(), SwapTags<A,B>() | UE_DEPRECATED(5.8) in MassCommandBuffer.h |
FMassCommandAddTagsInternal, FMassCommandAddFragmentsInternal | FMassCommandAddElements<T...> | UE_DEPRECATED(5.8) in MassCommands.h |
FMassCommandRemoveTagsInternal, FMassCommandRemoveFragmentsInternal | FMassCommandRemoveElements<T...> | UE_DEPRECATED(5.8) in MassCommands.h |
#include "MassExternalSubsystemTraits.h", "MassEntityElementTypes.h", "MassEntityFragments.h", "MassEntityHandle.h" | Mass/ExternalSubsystemTraits.h, Mass/EntityElementTypes.h, Mass/EntityFragments.h, Mass/EntityHandle.h | UE_DEPRECATED_HEADER(5.8) in each shim |
FMassEntityManager::Initialize() | Initialize(FMassEntityManagerStorageInitParams) with FMassEntityManager_InitParams_Concurrent | UE_DEPRECATED(5.8) in MassEntityManager.h |
UMassRepresentationSubsystem::GetOrSpawnActorFromTemplate | GetOrRequestSpawnActorFromTemplate | UE_DEPRECATED(5.8) in MassRepresentationSubsystem.h:246 |
FMassLookAtTargetTag | FMassLookAtTargetFragment | UE_DEPRECATED(5.6) in MassLookAtFragments.h |
Treating Mass as a plugin: MassEntity and MassCore are runtime modules with no .uplugin. Adding "MassEntity" to Build.cs is enough; only MassGameplay, MassAI and MassCrowd need enabling in the .uproject.
Wrong header for FTransformFragment: it lives in Mass/EntityFragments.h (module MassCore). MassCommonFragments.h merely includes it; MassCommon and MassEntity list MassCore as a public dependency so it resolves transitively, but include Mass/EntityFragments.h and list MassCore explicitly rather than relying on that.
Structural change during iteration: calling EntityManager.AddFragmentToEntity(...) inside ForEachEntityChunk relocates the entity and invalidates every view in flight. Use Context.Defer().AddFragment<T>(Entity).
Requirements declared in the constructor: the query is bound to its entity manager just before ConfigureQueries runs, so AddRequirement in the constructor trips the "Modifying requirements before initialization" check. Declare requirements only in ConfigureQueries.
Forgetting to register a default-constructed query: FMassEntityQuery MyQuery; silently matches nothing until RegisterQuery(MyQuery) runs. Prefer MyQuery(*this) in the constructor initializer list.
Caching an FMassEntityView: views point into archetype memory that moves. Rebuild the view from the handle at each use.
IsSet() as an existence test: a handle to a destroyed entity still reports IsSet()/IsValid() true. Ask EntityManager.IsEntityValid(Handle).
Access mismatch: requesting ReadOnly and then calling GetMutableFragmentView<T>() asserts. Match the view to the declared EMassFragmentAccess.
Observing only AddElement: entities created with the fragment already present raise CreateEntity, not AddElement. Use EMassObservedOperationFlags::Add.
Touching UObjects from a parallel processor: set bRequiresGameThreadExecution = true, or declare the subsystem through AddSubsystemRequirement and give it a TMassExternalSubsystemTraits specialisation that states the truth.
ue-state-trees — State Tree assets, tasks, evaluators and the Mass State Tree schemaue-ai-navigation — ZoneGraph, Smart Objects, NavMesh and perceptionue-async-threading — task graph, ParallelFor and thread-safety fundamentalsue-actor-component-architecture — actors and components on the other side of UMassAgentComponentue-cpp-foundations — USTRUCT/UCLASS reflection, subsystems, module layoutue-animation-system — animation for entities promoted to actors or skinned instancesue-procedural-generation — PCG and ISM authoring that feeds Mass spawningue-mover — the Mover plugin: movement modes, layered moves and rollback networking© 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-mass-entity of quodsoler/unreal-engine-skills.
Open the folder on GitHubat commit f3742d7
Ue Mass Entity 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 Mass Entity this skillquodsoler/unreal-engine-skills | 362 | — | ~7.7k | Automated safety check: Pass | MIT | |
| Debugging CodeJetBrains/skills | 366 | 1 repos | ~3.8k | Automated safety check: Pass | None | |
| Ue Specifiersfjz13/UnrealSpecifiers | 1.1k | — | ~1.4k | Automated safety check: Pass | Custom licence | |
| Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin | 338 | — | ~1.8k | Automated safety check: Pass | MIT | |
| Unreal Live CodingItalink/UnrealClientProtocol | 127 | — | ~1k | Automated safety check: Pass | MIT | |
| Unreal Cpp Gameplayukanwat/overtime | 387 | 1 repos | ~1.5k | Automated safety check: Pass | Apache-2.0 |
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
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…
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.
Italink/UnrealClientProtocol
Trigger Live Coding compilation via UCP. An agent skill from Italink/UnrealClientProtocol.
ukanwat/overtime
Write Unreal Engine 5 C++ gameplay code: the UCLASS/UPROPERTY/UFUNCTION reflection macros, the Gameplay Framework (GameMode, Pawn, Character, PlayerController, Actor components), and the module…
ukanwat/overtime
Set up player input in Unreal Engine 5 with Enhanced Input: Input Actions, Input Mapping Contexts, modifiers and triggers, adding the mapping context, and binding actions by ETriggerEvent.
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 writing or debugging Mass Entity ECS code in Unreal Engine C++ — processors, queries, fragments, tags, observers, traits, spawning and large-scale agent simulation. Ue Mass Entity is an agent skill from quodsoler/unreal-engine-skills. Use when writing or debugging Mass Entity ECS code in Unreal Engine C++ — processors, queries, fragments, tags, observers, traits, spawning and large-scale agent simulation.
Ue Mass Entity fits situations like: debugging Mass Entity ECS code in Unreal Engine C++ — processors; spawning and large-scale agent simulation; the user mentions MassEntity; FMassEntityQuery.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-mass-entity -a claude-code`. Or copy the skill folder (skills/ue-mass-entity in quodsoler/unreal-engine-skills) into .claude/skills/ue-mass-entity in your project. Claude Code loads it when a task matches its description.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-mass-entity -a codex`. Or copy the skill folder (skills/ue-mass-entity in quodsoler/unreal-engine-skills) into .agents/skills/ue-mass-entity 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-mass-entity -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-mass-entity, .gemini/skills/ue-mass-entity, .github/skills/ue-mass-entity and .opencode/skills/ue-mass-entity in your project.
SKILL.md names no scripts, command-line tools or credentials: Ue Mass Entity 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 Mass Entity is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.7k tokens (SKILL.md is roughly 31k 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 6.9k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Ue Mass Entity: Debugging Code (JetBrains/skills, 366 stars), Ue Specifiers (fjz13/UnrealSpecifiers, 1.1k stars), Unreal Engine MCP (EpicGames/unreal-engine-skills-for-claude-code-plugin, 338 stars) and Unreal Live Coding (Italink/UnrealClientProtocol, 127 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.