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.
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.
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 #
Polling pipeline
- The subsystem ticks once per frame and iterates registered sensors with a fair cursor.
- Each due query on a sensor runs
Internal_ComputeQuery— a worker-safe gather & distance filter. - Queries needing LOS, nav path, or acoustic traces mark themselves for game-thread finishing.
Internal_ApplyQueryruns on the game thread: resolves filters, diffs vs. last frame, fires events, pushes replicated state.- Work over the
MaxChecksPerFramebudget rolls to the next frame; the cursor advances so no sensor is starved.
Install #
- Copy the
Vordfolder into your project'sPlugins/directory. - Ensure Gameplay Abilities is enabled (Vord enables it automatically).
- 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
FVordMessagebroadcast path; when absent, the plugin builds and runs identically minus the GMS broadcast. - Regenerate project files and build.
- Open Project Settings → Plugins → Vord to verify defaults.
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:
| Module | Type | Loading Phase | Purpose |
|---|---|---|---|
Vord | Runtime | PreDefault | Components, subsystem, types, settings |
VordEditor | Editor | PostEngineInit | Manifest builder, query detail panel, validators |
VordTests | DeveloperTool | PostEngineInit | Automation 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
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).
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.
| Property | Type | Notes |
|---|---|---|
Tags | FGameplayTagContainer | Identity tags. Replicated. |
bActive | bool | Runtime toggle for stealth/disguise. Replicated. |
bSkipOnHLOD | bool | Prevents HLOD proxies from double-registering. |
bTrackMovement | bool | Enable 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. (NamedSetBeaconActiveto avoid shadowingUActorComponent::SetActive.)IsRegistered()— pure; useful for debugging.
SetTags. Mutating Tags directly at runtime skips the bucket refresh.
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
| Property | Type | Notes |
|---|---|---|
Queries | TArray<FVordQuery> | One sensor, many questions. |
DefaultPollHz | float | Fallback when a query sets PollHz = 0. |
bAutoRegister | bool | If true, registers with the subsystem on BeginPlay. (Under the Vord category — not the inherited bAutoActivate, which Vord does not use.) |
Events
| Delegate | Signature | Fires 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.
| Field | Default | Description |
|---|---|---|
Tag | — | Target tag. Child tags match unless bExactTagMatch is true. |
Range | 2000.0 | Detection radius in unreal units. |
ZTolerance | 400.0 | Only used for Euclidean + Z. |
PollHz | 0 | Rate for this query; 0 inherits the sensor default. |
DistanceMode | Euclidean | See Distance Modes. |
bRequireLOS | false | Adds a line trace on the configured channel. |
bServerAuthoritative | false | Evaluate on server, replicate to owning client. |
bExactTagMatch | false | Disable parent-inheritance matching. |
MessageChannel | None | Broadcast FVordMessage on this channel tag. |
QueryId | Auto | Stable 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
| Function | Purpose |
|---|---|
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 #
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 #
| Mode | Cost | When to use |
|---|---|---|
| Euclidean | ⚡ Cheapest — raw 3D DistSq | Default. Good for most gameplay. |
| Euclidean + Z | ⚡ Cheap — 2D + vertical gate | Top-down, level-aware music, multi-floor dungeons. |
| Nav Path | ⚙ Opt-in — async navmesh path length | AI / stealth reactions that respect geometry. Falls back to Euclidean if no navmesh. |
| Acoustic | ⚙ Opt-in — distance × occlusion multiplier | Perceptual approximation. Wire a provider for Steam Audio / Wwise fidelity. |
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.
- Add
AISenseConfig_Vordto the pawn'sUAIPerceptionComponent. - Place a
Vord Sensorand aVord → AI Perception Bridgeon the same actor. - Optionally filter which tags forward via
ForwardTagFilter, or adjustDefaultStrength.
Bridge component properties
| Property | Type | Notes |
|---|---|---|
Sensor | TWeakObjectPtr<UVordSensorComponent> | Auto-discovered on the same actor if left null. |
DefaultStrength | float (0..1) | Stimulus strength; 0 = ignored. |
ForwardTagFilter | FGameplayTagContainer | Empty = 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.
- Open the editor and use the menu: Vord → Rebuild Persistent Manifest.
- The builder scans
UActorDescContainers for actors with a beacon and records tags + bounds. - At runtime, the subsystem merges manifest entries into sensor results and dedupes against live beacons by
SourceActorGuid.
Replication & Server Authority #
- Beacons replicate
TagsandbActiveso clients see the same identity. - Sensor queries with
bServerAuthoritative = trueevaluate 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).
| Key | Default | Purpose |
|---|---|---|
HashCellSize | 6400 | Spatial-hash cell size (uu). |
DefaultPollHz | 10 | Fallback polling rate. |
MaxChecksPerFrame | 4096 | Global frame budget. |
GlobalPollScale | 1.0 | Scale-everything knob for low-end. |
bAsyncPollingEnabled | false | Compute phase via ParallelFor. |
bUsePersistentManifest | false | Enable WP-unloaded lookups. |
PersistentManifest | — | Soft ref to the manifest asset. |
bDebugDrawEnabled | false | In-world spheres + nearest links. |
MaxAcousticTracesPerFrame | 64 | Budget for acoustic traces. |
MaxNavQueriesPerSensorPerPoll | 4 | Budget for nav path queries. |
NavPathCacheTTL | 0.5s | TTL of cached path lengths. |
AcousticOcclusionMultiplier | 2.0 | Fallback occlusion factor. |
DefaultLOSTraceChannel | Visibility | Channel for LOS traces. |
AcousticTraceChannel | Visibility | Channel 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.
| CVar | Overrides |
|---|---|
p.Vord.HashCellSize | HashCellSize |
p.Vord.MaxChecksPerFrame | MaxChecksPerFrame |
p.Vord.GlobalPollScale | GlobalPollScale |
p.Vord.AsyncEnabled | bAsyncPollingEnabled |
p.Vord.DebugDraw | bDebugDrawEnabled |
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. Reserve20-30 Hzfor tight combat gates. - Async. Flip
p.Vord.AsyncEnabled 1once profiled — the game-thread cost drops to just the apply/events phase. - Budget.
MaxChecksPerFrameis your ceiling. The round-robin cursor keeps any single frame from starving. - Exact match. Prefer
bExactTagMatch = trueon 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
VordTestsmodule (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.