Appearance
Mass Forge C++ high-volume attribute access
Intentionally C++ only
Processor-level iteration, compiled fragment access, and million-entity hot paths stay in C++ so they can remain allocation-free and avoid moving huge handle arrays through Blueprint. Blueprint remains the supported authoring and orchestration surface for ordinary gameplay-scale operations.
Blueprint and subsystem calls are designed for gameplay orchestration. A Mass processor that touches thousands of entities should compile attribute names once and then use slot-based access inside its entity loop.
Compile before the hot loop
cpp
#include "Attributes/MF_CompiledAttribute.h"
#include "Subsystems/MF_AttributeSubsystem.h"
FMFAttributeId HealthId;
HealthId.Domain = EMFAttributeDomain::Vital;
HealthId.Name = TEXT("Health");
FMFCompiledAttribute HealthBinding;
const EMFAttributeAccessResult CompileResult =
AttributeSubsystem->CompileAttribute(HealthId, HealthBinding);Keep the binding only when CompileResult is Success. Compilation performs the schema/name lookup and copies the slot and clamp policy into a small value type.
Use fragment views in a processor
Require the three Mass Forge attribute fragments in the query, then resolve each entity without subsystem calls, allocation, asset access, or FName lookup:
cpp
TArrayView<FMF_VitalAttributesFragment> Vitals =
Context.GetMutableFragmentView<FMF_VitalAttributesFragment>();
TArrayView<FMF_CombatAttributesFragment> Combat =
Context.GetMutableFragmentView<FMF_CombatAttributesFragment>();
TArrayView<FMF_SupportAttributesFragment> Support =
Context.GetMutableFragmentView<FMF_SupportAttributesFragment>();
for (int32 EntityIndex = 0; EntityIndex < Context.GetNumEntities(); ++EntityIndex)
{
const FMFAttributeChangeResult Change = UE::MassForge::ApplyCompiledAttribute(
Vitals[EntityIndex],
Combat[EntityIndex],
Support[EntityIndex],
HealthBinding,
EMFAttributeOperation::Add,
-10.0f);
}ReadCompiledAttribute provides the equivalent const read path. ResolveCompiledAttribute is available when a custom processor needs the raw value pointer.
Schema refresh safety
Every binding records the attribute subsystem's schema generation. Check it once before scheduling or entering a batch:
cpp
if (!AttributeSubsystem->IsCompiledAttributeCurrent(HealthBinding))
{
// Recompile outside the Mass execution loop.
}RefreshSchemas invalidates every earlier binding, even when the apparent slot did not change. This prevents callers from silently carrying an old clamp policy into a new schema generation.
Events and threading
Compiled access intentionally does not broadcast Blueprint delegates. Broadcasting per entity would defeat the batch path and is unsafe from worker threads. A processor that needs presentation events should collect a bounded summary and hand it to a game-thread presentation system after processing.
For game-thread orchestration, the attribute, Instant Effect, Gameplay Tag, and Persistent Effect Blueprint delegates have corresponding Native multicast mirrors. Ability transactions defer both forms until all participating state has committed and discard them together on rollback.
Do not call the direct Blueprint/subsystem mutation functions while Mass is processing. Use compiled fragment access from processors and the bounded queued APIs from external gameplay code.
Compiled effect application and removal
For repeated multi-operation effects, add Mass Forge High Volume Effects Trait and author an explicit Apply/Remove Instant Effect pair. The trait resolves attributes into slots once and stores the fixed-capacity table in a const-shared archetype fragment. A producer processor submits by cached numeric index through RequestHighVolumeEffect; the built-in UMF_HighVolumeEffectsProcessor commits the complete attribute/tag side atomically and retains one bounded completion per entity. This path also synchronizes active persistent-modifier base values.
It supports finite context-free operations only and deliberately emits no per-entity delegates. Context parameters, source/target captures, duration, stacking, handles, and presentation events remain on the normal effect APIs. See the high-volume compiled effects guide for setup, ordering, back-pressure, completion, and removal semantics.
Memory before throughput
Call UMF_PerformanceBlueprintLibrary::GetMassForgeMemoryFootprint() in a diagnostic or capacity-planning path before choosing a population archetype. It reports exact native payloads for the current build and distinguishes per-entity fragments from the const-shared Derived Attributes graph. See the memory and capacity guide for verified Win64 sizes, preset totals, exclusions, and the required packaged profiling workflow.
Mass Forge's built-in processors are protected by a source-level processor hot-loop performance contract. New processors must keep name lookup, asset loading, delegates, dynamic containers, allocation sites, reflection, and logging outside their marked entity-iteration region.