Vord — Tag-Driven Proximity Awareness
Darksaint Games · Unreal Engine 5.7+

Vord Documentation

A guardian at the edge of your world. Lightweight beacons, tagged sensors, and a spatially-hashed subsystem that answers “what's near me?” reliably and cheaply — built for World Partition, level streaming, and replication.

UE 5.7.0 Gameplay Runtime + Editor Beta v0.1.0 GameplayAbilities GameplayMessageRouter (optional)

Overview #

Vord gives every actor in your world two tools: a beacon (“I exist, and these are my tags”) and a sensor (“tell me when anything tagged X is within Y units”). A per-world subsystem drives the polling loop against a spatial hash, dispatches Blueprint events, and optionally replicates authoritative results to owning clients — all without a single component tick.

It is deliberately small in surface area and deliberately correct in the details: lazy registration that survives World Partition streaming, a per-frame check budget to cap worst-case cost, optional async evaluation via ParallelFor, and opt-in advanced distance modes (navmesh path, acoustic occlusion, line-of-sight) that stay off the hot path until you ask for them.

Use it for music layering, combat gates, stealth awareness, interaction prompts, AI senses, fast-travel blockers, horde density, ambient reactivity, boss arenas.

Features #

Tag-driven

Everything keys off FGameplayTag. Exact match or parent inheritance per query.

Zero-tick beacons

Beacons self-register on BeginPlay. No actor ever ticks just to be detectable.

Spatial hash

O(1) bucket lookup with a configurable cell size; only nearby cells are walked per query.

Multi-query sensors

One sensor composes many questions (short-range combat + long-range music on one boss).

Async evaluation

Compute phase runs on workers; apply/events remain on the game thread.

Replicated results

Server-authoritative queries replicate state to the owning client with delta-replay of events.

AI Perception bridge

Drop-in UAISense_Vord so controllers see proximity stimuli alongside Sight/Hearing.

Message router (optional)

If the GameplayMessageRouter plugin is present, Vord broadcasts FVordMessage on per-query channel tags — otherwise compiled out transparently.

World Partition aware

Optional cook-time Persistent Manifest answers long-range queries across unloaded cells.

Action gates

Project-level rules block tagged actions (fast travel, save, interact) by proximity.

Architecture #

UVordBeaconComponentLightweight advertiser. Replicated tags + active flag.
UVordWorldSubsystemSpatial hash, polling loop, budget, acoustic provider, manifest.
UVordSensorComponentList of queries. Emits entered/exited/nearest/count events.
FVordSpatialHashBucketed registry keyed by cell; membership by tag container.
UVordPersistentManifestCooked list of permanent beacons for long-range gather.
UAISense_Vord + BridgeForwards events into UE's AI perception pipeline.

Polling pipeline

  1. The subsystem ticks once per frame and iterates registered sensors with a fair cursor.
  2. Each due query on a sensor runs Internal_ComputeQuery — a worker-safe gather & distance filter.
  3. Queries needing LOS, nav path, or acoustic traces mark themselves for game-thread finishing.
  4. Internal_ApplyQuery runs on the game thread: resolves filters, diffs vs. last frame, fires events, pushes replicated state.
  5. Work over the MaxChecksPerFrame budget rolls to the next frame; the cursor advances so no sensor is starved.
Correctness Async mode produces identical results to sync mode. Only throughput changes.

Install #

  1. Copy the Vord folder into your project's Plugins/ directory.
  2. Ensure Gameplay Abilities is enabled (Vord enables it automatically).
  3. Optional: enable Gameplay Message Router (ships with the Lyra sample / Common Game Samples). When present, Vord auto-detects it at build time and compiles in the FVordMessage broadcast path; when absent, the plugin builds and runs identically minus the GMS broadcast.
  4. Regenerate project files and build.
  5. Open Project Settings → Plugins → Vord to verify defaults.
How GMS detection works Vord.Build.cs scans for GameplayMessageRouter.uplugin under the engine or project plugins. If found, it links GameplayMessageRuntime and defines WITH_VORD_GMS=1; otherwise WITH_VORD_GMS=0 and the broadcast call is a no-op.

Module layout:

ModuleTypeLoading PhasePurpose
VordRuntimePreDefaultComponents, subsystem, types, settings
VordEditorEditorPostEngineInitManifest builder, query detail panel, validators
VordTestsDeveloperToolPostEngineInitAutomation tests for the subsystem

Quick Start #

1. Tag your enemies

Add a Vord Beacon component to your enemy actor and set its Tags to Enemy.Boss, Faction.Undead.

2. Listen from your player

Add a Vord Sensor component to your player pawn. Configure one query:

Queries[0]:
  Tag:              Enemy.Boss
  Range:            3000                  // 30 m — see note below
  DistanceMode:     Euclidean
  bExactTagMatch:   false                 // also matches Enemy.Boss.*
  MessageChannel:   Vord.Music.Combat
Units Range and ZTolerance are in Unreal units (centimeters). 2000 = 20 m, 100 = 1 m. If your event never fires, this is the first thing to check.

3. React in Blueprint

Bind OnTagEntered / OnTagExited on the sensor, or subscribe to the Vord.Music.Combat channel via the Gameplay Message Subsystem (requires the optional GameplayMessageRouter plugin).

Tip For moving enemies, keep bTrackMovement = true on the beacon so the subsystem re-buckets them as they traverse cells.

Beacon Component #

Attach UVordBeaconComponent to any actor that should be detectable. Beacons never tick. They self-register with the subsystem on BeginPlay and deregister on EndPlay, so World Partition streaming and Data-Layer loads are handled with zero glue.

PropertyTypeNotes
TagsFGameplayTagContainerIdentity tags. Replicated.
bActiveboolRuntime toggle for stealth/disguise. Replicated.
bSkipOnHLODboolPrevents HLOD proxies from double-registering.
bTrackMovementboolEnable on anything that moves.

Blueprint functions

  • SetTags(NewTags) — replace the tag set and keep the subsystem's per-tag index in sync.
  • SetBeaconActive(bNewActive) — toggle registration without destroying the component. (Named SetBeaconActive to avoid shadowing UActorComponent::SetActive.)
  • IsRegistered() — pure; useful for debugging.
Do Always go through SetTags. Mutating Tags directly at runtime skips the bucket refresh.
Note The Auto Activate checkbox under the component's Activation category is the inherited UActorComponent flag and is not what gates Vord registration. Beacons register in BeginPlay regardless; the bActive field under the Vord category is the one that matters.

Sensor Component #

Attach UVordSensorComponent to anything that needs awareness. The sensor itself does not tick — the world subsystem drives it.

Key properties

PropertyTypeNotes
QueriesTArray<FVordQuery>One sensor, many questions.
DefaultPollHzfloatFallback when a query sets PollHz = 0.
bAutoRegisterboolIf true, registers with the subsystem on BeginPlay. (Under the Vord category — not the inherited bAutoActivate, which Vord does not use.)

Events

DelegateSignatureFires when…
OnTagEntered(Tag, Source, Distance)A new matching beacon appears in range.
OnTagExited(Tag, Source)A matching beacon leaves range / deactivates.
OnNearestChanged(Tag, NewNearest, OldNearest)The nearest actor for a tag switches.
OnTagCountChanged(Tag, NewCount, OldCount)Count of in-range matches changes.

Blueprint API

  • AddQuery(Query), RemoveQueriesWithId(Id), ClearQueries()
  • ForceImmediateEvaluation() — bypass the timer for this frame (use after teleports).
  • SetSensorActive(bNewActive) — pause/resume without unregistering.
  • GetTagState(Tag), IsTagInRange(Tag), GetAllTagStates(Out)

Query Struct #

A FVordQuery is a single question on a sensor. Compose several on one sensor to get layered reactions for the same tag at different ranges.

FieldDefaultDescription
TagTarget tag. Child tags match unless bExactTagMatch is true.
Range2000.0Detection radius in unreal units.
ZTolerance400.0Only used for Euclidean + Z.
PollHz0Rate for this query; 0 inherits the sensor default.
DistanceModeEuclideanSee Distance Modes.
bRequireLOSfalseAdds a line trace on the configured channel.
bServerAuthoritativefalseEvaluate on server, replicate to owning client.
bExactTagMatchfalseDisable parent-inheritance matching.
MessageChannelNoneBroadcast FVordMessage on this channel tag.
QueryIdAutoStable identifier for debug and targeted removal.

Example: layered boss reactions

// Music cue at 30m, combat gate at 8m, same tag.
Queries:
  - { Tag: Enemy.Boss, Range: 3000, MessageChannel: Vord.Music.Combat }
  - { Tag: Enemy.Boss, Range:  800, MessageChannel: Vord.Gate.Engage,
      bRequireLOS: true, bServerAuthoritative: true }

World Subsystem #

UVordWorldSubsystem is the coordinator. Access it via UVordWorldSubsystem::Get(WorldContext). All public API is game-thread only.

Blueprint-facing API

FunctionPurpose
GatherInRange(Tag, Origin, Radius, bExactTagMatch, OutActors)Ad-hoc radius query. Use sparingly — sensors are usually cheaper.
CanPerformAction(ActionTag, Instigator)Evaluates project-level blocking rules. Returns a struct with the blocking tag/actor/distance.
GetRegisteredBeaconCount()Debug helper.
SetAcousticProvider(UObject*)Hot-swap the acoustic multiplier source (Steam Audio, Wwise, custom).
ReloadPersistentManifest()Force the manifest to reload from settings.

Gameplay Messages #

Optional dependency The message-bus path requires the GameplayMessageRouter plugin (not shipped with stock UE 5.7 — it ships with Lyra / Common Game Samples). Vord auto-detects it; if the plugin is absent, broadcasts are compiled out and the rest of Vord works unchanged.

Any query with a MessageChannel tag publishes a FVordMessage to the 5.7 UGameplayMessageSubsystem every time its state changes. Subscribers need no hard references to either sensor or beacon.

Convention: Vord.<Subsystem>.<Event> — e.g. Vord.Music.CombatEntered, Vord.FastTravel.Blocked.

// Payload
FVordMessage {
  QueryTag, Channel,
  Sensor, SensorActor,
  NearestActor, NearestDistance,
  Count, PreviousCount
}

Distance Modes #

ModeCostWhen to use
Euclidean⚡ Cheapest — raw 3D DistSqDefault. Good for most gameplay.
Euclidean + Z⚡ Cheap — 2D + vertical gateTop-down, level-aware music, multi-floor dungeons.
Nav Path⚙ Opt-in — async navmesh path lengthAI / stealth reactions that respect geometry. Falls back to Euclidean if no navmesh.
Acoustic⚙ Opt-in — distance × occlusion multiplierPerceptual approximation. Wire a provider for Steam Audio / Wwise fidelity.
Budgeted Acoustic traces and nav queries are rate-limited via settings (MaxAcousticTracesPerFrame, MaxNavQueriesPerSensorPerPoll). Work that doesn't fit the budget rolls to the next frame.

AI Perception Integration #

Vord ships a first-class AI sense, UAISense_Vord, plus a drop-in UVordPerceptionBridgeComponent that forwards a sensor's entered/exited events into the AI perception pipeline automatically.

  1. Add AISenseConfig_Vord to the pawn's UAIPerceptionComponent.
  2. Place a Vord Sensor and a Vord → AI Perception Bridge on the same actor.
  3. Optionally filter which tags forward via ForwardTagFilter, or adjust DefaultStrength.

Bridge component properties

PropertyTypeNotes
SensorTWeakObjectPtr<UVordSensorComponent>Auto-discovered on the same actor if left null.
DefaultStrengthfloat (0..1)Stimulus strength; 0 = ignored.
ForwardTagFilterFGameplayTagContainerEmpty = forward all tags. Populated = only forward matching tags.

For custom strength mapping per tag, bind to the sensor events directly and call UAISense_Vord::ReportVordEvent yourself — the bridge just registers stimuli directly on the target actor's UAIPerceptionComponent.

Acoustic Providers #

Implement IVordAcousticProvider and register the object with UVordWorldSubsystem::SetAcousticProvider. The provider is called per Acoustic-mode query and must be cheap.

class FMyAudioProvider : public IVordAcousticProvider {
  virtual float ComputeAcousticMultiplier(
      const UObject* World,
      const FVector& Listener,
      const FVector& Source) const override;
};

Return 1.0 for no attenuation; larger values mean the signal is effectively farther away. Without a provider, Vord uses a single occlusion trace and the AcousticOcclusionMultiplier setting.

Persistent Manifest (World Partition) #

When sensor ranges exceed the loaded world slice, turn on bUsePersistentManifest in settings and point it at a UVordPersistentManifest data asset.

  1. Open the editor and use the menu: Vord → Rebuild Persistent Manifest.
  2. The builder scans UActorDescContainers for actors with a beacon and records tags + bounds.
  3. At runtime, the subsystem merges manifest entries into sensor results and dedupes against live beacons by SourceActorGuid.
Note The manifest does not replace live beacons — it augments them. Anything currently streamed always wins.

Replication & Server Authority #

  • Beacons replicate Tags and bActive so clients see the same identity.
  • Sensor queries with bServerAuthoritative = true evaluate on the authority only.
  • Results land on the owning client via ReplicatedStates (RepNotify).
  • The client replays entered/exited events from the delta, so gameplay reactions are identical on both sides without double-evaluation.

For LOS / nav / acoustic modes, keep the authoritative flag on to avoid clients running traces against imperfectly-replicated geometry.


Settings #

Project Settings → Plugins → Vord (or edit DefaultVord.ini).

KeyDefaultPurpose
HashCellSize6400Spatial-hash cell size (uu).
DefaultPollHz10Fallback polling rate.
MaxChecksPerFrame4096Global frame budget.
GlobalPollScale1.0Scale-everything knob for low-end.
bAsyncPollingEnabledfalseCompute phase via ParallelFor.
bUsePersistentManifestfalseEnable WP-unloaded lookups.
PersistentManifestSoft ref to the manifest asset.
bDebugDrawEnabledfalseIn-world spheres + nearest links.
MaxAcousticTracesPerFrame64Budget for acoustic traces.
MaxNavQueriesPerSensorPerPoll4Budget for nav path queries.
NavPathCacheTTL0.5sTTL of cached path lengths.
AcousticOcclusionMultiplier2.0Fallback occlusion factor.
DefaultLOSTraceChannelVisibilityChannel for LOS traces.
AcousticTraceChannelVisibilityChannel for acoustic traces.
BlockingRules[]Drive CanPerformAction.

Blocking rules example

BlockingRules:
  - ActionTag:  Action.FastTravel
    BlockerTags: [ Enemy.Hostile, Hazard.Combat ]
    OverrideRange: 1500
    bExactActionMatch: false

Console Variables #

Every perf-critical setting has a CVar mirror for runtime tuning.

CVarOverrides
p.Vord.HashCellSizeHashCellSize
p.Vord.MaxChecksPerFrameMaxChecksPerFrame
p.Vord.GlobalPollScaleGlobalPollScale
p.Vord.AsyncEnabledbAsyncPollingEnabled
p.Vord.DebugDrawbDebugDrawEnabled

Performance Tuning #

  • Cell size. Rule of thumb: ~2× your largest common sensor range. Too small → many bucket walks; too large → many per-bucket checks.
  • Poll rates. Music cues and ambient states are fine at 2-5 Hz. Reserve 20-30 Hz for tight combat gates.
  • Async. Flip p.Vord.AsyncEnabled 1 once profiled — the game-thread cost drops to just the apply/events phase.
  • Budget. MaxChecksPerFrame is your ceiling. The round-robin cursor keeps any single frame from starving.
  • Exact match. Prefer bExactTagMatch = true on hot queries; parent-matching is slightly more work.
  • LOS / Nav / Acoustic. Keep these off default queries. They are designed to be opt-in filters on the few that matter.

Debug & Stats #

  • p.Vord.DebugDraw 1 — draws sensor spheres, in-range beacons, and nearest links.
  • stat Vord — exposes per-frame counts for gather, filter, and apply phases.
  • Automation tests live in the VordTests module (DeveloperTool) and run under Session Frontend → Automation.

Recipes #

Combat music layer

Sensor on Player:
  Query: Tag=Enemy.Hostile, Range=3500, PollHz=4,
         DistanceMode=Euclidean, MessageChannel=Vord.Music.Combat

Music subsystem subscribes to Vord.Music.Combat and crossfades
when Count transitions 0 <-> 1.

Fast-travel gate

UVordSettings.BlockingRules:
  - ActionTag=Action.FastTravel, BlockerTags=[Enemy.Hostile], OverrideRange=1500

Before starting fast travel:
  Result = UVordWorldSubsystem::CanPerformAction(Action.FastTravel, Player);
  if (!Result.bAllowed) show “Cannot fast travel while {Result.BlockingTag} is nearby”.

Stealth AI with nav-path distance

Sensor on Guard:
  Query: Tag=Player, Range=2000, DistanceMode=NavPath,
         bRequireLOS=true, PollHz=8, bServerAuthoritative=true

AI reacts only when the player is both visible and actually
reachable within the ranged nav-path budget.

Cross-cell long-range detection

Enable bUsePersistentManifest + assign the cooked manifest asset.
Rebuild after changes via “Vord → Rebuild Persistent Manifest”.
Long-range Enemy.Siege queries now see unloaded-cell beacons.

FAQ #

Does Vord replace overlap volumes?

For tag-driven, range-based awareness — yes, and at a fraction of the cost. For trigger volumes with bespoke shapes, keep using the engine primitives.

Do beacons and sensors tick?

No. Only the world subsystem ticks, and it evaluates due queries in a round-robin with a frame budget.

What happens when World Partition unloads an enemy?

Its beacon calls UnregisterWithSubsystem on EndPlay automatically. If you also want long-range detection of unloaded entities, enable the Persistent Manifest.

Can multiple sensors share queries?

Each sensor owns its own query list, but they share the subsystem's spatial hash and budget. Duplicate identical queries are fine; they're cheap.

Is it deterministic?

Within a single frame on one machine, yes. Across machines, sensors marked bServerAuthoritative are deterministic per replication tick.