Open-World Narrative · Architecture

Audio, VFX, Cinematics & UI

A focused page within the Open-World Narrative Architecture documentation. The full map and every sibling page live in the Architecture hub.

8sections12 minread1diagram

On this page

V5 is one open-world narrative game that has to sound, spark, cut, and read like seven at once: the neon pulse of an Urban heist, the AM-radio hiss of a 1947 Period interrogation, the wide golden-hour swell of a Frontier outlaw trail, the medieval-Slavic sign-craft of a Hunter contract, the electronic-orchestral hybrid of a Sci-Fi boarding op, and the white-room hush of a cross-cell Mind Palace deduction — all emitted by one shared presentation stack keyed on the same EV5Cell enum the gameplay layer routes on. Four Unreal C++ modules own that job: V5Audio (MetaSound voice routing, the dialogue ducking director, dynamic per-cell music, period radio, DualSense haptics, Dolby/Sony/Steam spatial backends, and the shipping audio content manifest), V5VFX (Niagara catalogs for muzzle/blood/debris, the five Witcher signs, sci-fi biotic/tech powers, weather, vehicle damage, the Mind Palace evidence orb, and a per-quality-tier particle budget), V5Cinematics (Sequencer style catalog, an 8,000-setup per-companion camera library, the pre-rendered master pipeline, a full Director-Mode NLE, a cross-cell replay editor, and the Period behind-the-scenes documentary viewer), and V5UI (the CommonUI shell, six per-cell HUDs, the dialogue wheel, the volumetric Mind Palace room, photo mode, the companion-app bridge, and a 16-language menu localization manifest). Where the netcode and GAS layers must be provably correct, this layer has the inverse remit: it is cosmetic, it may cost whatever the platform budget allows, and its one hard rule is that it must never write back into state the simulation hashes. This page is part of the Platform, Services & Live Operations group; the section hub is ../V5_ARCHITECTURE.md.

What ships, honestly#

The four modules are real, deterministic Unreal C++ that builds and is exercised by automation, but they are a decision, data, and validation layer, and the honest distance from the engine runtime differs sharply per module. Six qualifications so the rest of the page reads at face value:

  1. These modules are pure-function builders, not stateful subsystems. Unlike V4's UGameInstanceSubsystem dispatchers, every entry point here is a static BlueprintPure method on a UBlueprintFunctionLibrary (UV5_Audio_RouterSubsystem, UV5_VFX_Budget, UV5_Cine_DirectorMode, UV5_UI_Shell, …). They take inputs and return manifests, view-models, or validation structs with no side effects, so the same call yields the same answer on every machine and every rule is unit-testable without a live world.

  2. V5UI is the one module with genuine engine-runtime instantiation — and it is substantial. V5UIWidgets.cpp ships real UCommonActivatableWidget / UUserWidget subclasses that build their own widget trees at runtime via WidgetTree->ConstructWidget<>(), plus a real AV5_UI_MindPalaceVolumetricRoom AActor that spawns USceneComponents into a UWorld. The widget tests NewObject<> these widgets and SpawnActor<> the room into a transient world and assert their built trees. This is a larger live-engine surface than V4's single MVVM touch.

  3. The other three modules link their middleware loosely — or not at all. V5VFX.Build.cs links the real Niagara module but never calls UNiagaraFunctionLibrary — it builds system definitions and budget math. V5Audio.Build.cs and V5Cinematics.Build.cs do not even link MetasoundEngine, MovieScene, or Sequencer; their MetaSound graph ids and level sequence paths are soft FName / FSoftObjectPath references to content that is named but not authored.

  4. There are zero binary .uasset presentation assets. V5/ue/Content holds no .uasset at all. The soft paths the C++ builds — /Game/V5VFX/Niagara/…, /Game/V5Cinematics/…, /Game/V5/UI/… — name content that is specified but pending. Three JSON sidecars (V5/audio/audio-production-manifest.json, V5/cinematics/cinematic-asset-manifest.json, cinematic-director-mode-manifest.json) are schema-versioned design contracts, honestly labeled as data.

  5. The decision math is genuine and value-pinned. Distance attenuation in decibels, the dB→amplitude loudness sum, dialogue ducking, the per-quality Niagara budget, the Fibonacci-sphere orb layout, and the radial dialogue-wheel geometry are real algorithms asserted against specific computed numbers across 22 automation specs (4 audio + 3 VFX + 7 cinematics + 8 UI). They would fail against a hardcoded return.

  6. The validators fail loud. ValidateCameraBudget, ValidateDirectorModeTool, ValidateCrossCellReplayEditor, ValidateDocumentary, and ValidateTier2State accumulate a TArray<FString>/Issues list and only set bValid when it is empty — they reject drift (wrong counts, missing approval, overlapping clips) rather than rubber-stamping.

Everything below is real where it cites a function and a line; where it names an authored asset or an un-called plugin, that is the specified-but-pending part.

The shared shape: builders, validators, one real widget runtime#

flowchart TD subgraph BFL["V5 presentation — pure-function C++ (this page)"] AUD["V5Audio<br/>Router · DuckingDirector · DynamicMusic · PeriodRadio · Haptics · ContentManifest"] VFX["V5VFX<br/>Niagara catalogs + per-tier particle budget"] CIN["V5Cinematics<br/>Styles · 8k camera lib · DirectorMode NLE · ReplayEditor · Documentary"] UI["V5UI<br/>Build*State view-models + validators"] end GAS["GAS verbs / combat / dialogue / heist"] --> AUD & VFX & CIN UI -->|reads, never writes| GAS UI ==>|"NewObject / SpawnActor (real)"| RT["Live UWorld: CommonUI widgets + MindPalace AActor"] VFX -. "links but never calls" .-> NIA["Niagara module"] AUD -. soft FName .-> MS["MetaSound graphs — not authored, not linked"] CIN -. soft path .-> LS["LevelSequence .uasset — not authored, Sequencer not linked"] UI -. soft class .-> WBP["WBP_* designer assets — not authored"]

The thick edge is the boundary that is genuinely crossed: V5UI instantiates and runs engine objects. The dashed edges are soft references awaiting authored content (and, for audio/cinematics, a plugin link as well).

Audio — V5Audio#

Voice routing and the spatial mix#

UV5_Audio_RouterSubsystem::BuildVoiceRoute (V5AudioSystems.cpp:147) stamps a voice source onto the dialogue bus with a cell-tuned attenuation radius (Sci-Fi 40 m, others 28 m), a Mind-Palace priority bump (90 vs 75), occlusion enabled for every non-stereo backend, and a per-cell/per-backend MetaSound graph id. The real math is EvaluateSpatialMix (:205): for each route on the requested backend within radius it computes a distance attenuation clamp(distMeters × −0.8, −36, 0) dB, accumulates loudness as Σ pow(10, (VolumeDb + AttenDb) / 20), converts back with 20 × log₁₀(Σ), tracks the highest-priority audible source, and flags bWithinBackendBudget against the backend's MaxSpatialSources. The V5.Audio.SpatialMixing spec feeds four routes — one in range, one priority-120 in range, one 1 km away, one on a different backend — and asserts exactly two audible Dolby sources, voice.priority selected, and loudness above −30 dB: a hardcoded return could not satisfy all four.

Dialogue ducking and dynamic music#

UV5_Audio_DialogueDirector::ApplyDialogueDucking (:265) subtracts a real dB offset from the mix — music −9 dB and radio −14 dB under full dialogue, a lighter −3 / −5 dB in bark-only mode — and the spec asserts the bark duck leaves music louder than the dialogue duck, a relation only correct arithmetic produces. BuildMixSnapshot (:165) sets per-state bus levels (Combat music −1 dB, Cinematic −2/−5, Dialogue −6/−5, Mind Palace −4/−8) and auto-applies ducking when dialogue is active. UV5_Audio_DynamicMusic::SelectMusicState (:310) resolves the priority order Mind Palace → Cinematic → Combat → Exploration (the spec proves Mind Palace wins even with combat+cinematic also true), and BuildDynamicMusicGraph emits a per-cell layered-stem graph with a faster Sci-Fi transition (1.25 s vs 2.0 s).

Period radio, haptics, and the content manifest#

UV5_Audio_PeriodRadio::BuildPeriodRadioMetaSound (:291) gates the band on the era: AM-only at EraYear ≤ 1947 (period_am bank), FM at ≥ 1968 or in the Urban cell (period_fm) — asserted at 1947 and 1968. BuildHapticCue (:342) returns DualSense profiles with distinct low/high motor frequencies and an intensity clamp: Weapon (120/220 Hz, adaptive-trigger, 0.08 s, transient), HorseTrot (55/92 Hz, looping, 0.32 s), GravityTransition (35/180 Hz, sustained 1.2 s). BuildShippingContentManifest (:391) assembles the launch audio budget and computes — not asserts — its own pass flags: three composer clusters covering all five primary cells, five score budgets totalling 40 original-score hours, nine SFX categories summing to 4,730 unique cues (floor 4,500), twelve VO languages × 10,000 = 120,000 recorded lines, 18 period radio stations + 140 TV channels, and three binaural backends (Dolby 128 / Sony 360 96 / Steam 128 sources). V5.Audio.BackendsHapticsAndContent pins every one of those numbers.

VFX — V5VFX#

V5VFX is a Niagara catalog and budget module: it builds typed system definitions with soft /Game/V5VFX/Niagara/… paths, GPU-sim flags, and per-platform particle caps, then proves a quality-tier budget over them — it never spawns a particle. The catalog families (V5VFXSystems.cpp) are the three shared impacts (muzzle/blood/debris), the five Witcher signs each with a base and a charged variant (10 variants, charged spawn rate 48 vs base 24), five sci-fi biotic/tech powers, five weather systems (rain/snow/dust/fog/solar-flare, each carrying a visibility multiplier), three Chaos-gated vehicle-damage systems, the Mind Palace evidence orb (with a high-contrast MPC swap), and seven per-cell emission curves. BuildAllNiagaraSystems (:220) composes them into a 22-system catalog (asserted exactly).

EvaluateNiagaraBudget (:244) is the real gate. Each quality tier carries a particle cap, a visible-system cap, and a BudgetScale: Switch 2 Performance 9,000 / 32 / 0.6×, Switch 2 Quality 14,000 / 36 / 1.0×, Console 32,000 / 72 / 1.5×, PC Ultra 64,000 / 128 / 2.0×. Estimated particles are Σ round(MaxParticlesSwitch2 × BudgetScale) across the catalog, and bWithinBudget requires both the particle and the system count under cap. The V5.VFX.Switch2Budget spec asserts the 22-system catalog fits the two Switch 2 tiers and that the Quality cap is stricter than Console. BuildPerCellEmissionCurves (:207) emits a real three-key attack-peak-release envelope (start 0/0, peak at t = 0.35, release at t = 1.0) with a per-cell peak scale (Hunter 1.15, Sci-Fi 1.25, Mind Palace 0.75), verified for shape and ordering. The pending inch is uniform: turn a definition into a UNiagaraFunctionLibrary::SpawnSystem* call against an authored system.

Cinematics — V5Cinematics#

This is the richest of the four modules and models cinematics as typed contracts plus fail-loud validators rather than a live ULevelSequencePlayer.

Style catalog and sequencer beats. BuildStyleCatalog (:410) encodes the four documented cinematography languages with real lens data: Noir (50 mm, 42° FOV, 16:9, high-contrast, Dutch angles — Urban/Period/Steampunk), Epic Vista (24 mm, 70°, 2.39:1 — Frontier/Hunter), Handheld Doc-Cine (35 mm, 58° — Sci-Fi), and Cinematic Widescreen (40 mm, 2.39:1 — Sci-Fi/Mind Palace). BuildSequencerCinematic (:390) lays a four-shot Establishing→Closeup→OverShoulder→ActionBeat spine over a clamped duration, and BuildCampaignBeatManifest (:579) emits 256 in-engine beats that ValidateSequencerBudget (:1338) checks for in-engine count, a duration cap, and present sequence paths.

The per-companion camera library. BuildPerCompanionCameraLibrary (:463) generates 8 companions × 5 cells × 200 setups = 8,000 camera setups, each with a cell-derived rig, focal length, boom length, and projected shot coverage summing to 30,000 — every number asserted in V5.Cinematics.CameraLibraryBudget. ValidateCameraBudget (:489) rejects any drift in the counts and any setup that is not director-approved.

Pipeline, Director Mode, replay editor, documentary. BuildPipeline (:540) fixes the 4K master pipeline (DPX + OpenEXR masters, AV1 + H.265 delivery, ACEScg HDR) with twelve key story moments. BuildDirectorModeTool (:612) and its validator (:699) are a genuine non-linear editor contract: five timeline tracks (Video/Camera/Audio/Subtitle/Marker), twelve clips, eleven cuts (hard / dissolve / match / J / L, with J/L/dissolve cuts requesting audio pre-roll), and three Movie Render Queue export presets — the validator enforces unique ids, in-bounds track references, continuity-checked cuts, and non-destructive editing. BuildCrossCellReplayEditor (:853) and ValidateCrossCellReplayEditor (:918) extend that to a privacy-aware splice tool: two source clips per cell, N−1 splices, and validation that every clip is rights-cleared, privacy-scrubbed, replay-hash-verified, non-overlapping, and that every splice crosses a cell boundary with audio normalization. BuildPeriodBehindTheScenesDocumentary (:1061) builds a 42-minute, 8-chapter, 24-still viewer with theater / chapter-select / still-gallery modes, and ValidateDocumentary (:1218) checks chapter start-time continuity and Period/Noir scoping.

UI / HUD — V5UI#

The real widget runtime#

V5UI is the module that touches the engine for real. The data layer is a family of Build*State pure functions — shell, main menu, cell select, settings, the six per-cell HUD models, the dialogue wheel, the volumetric Mind Palace, photo mode, the companion-app bridge, and localization. The runtime layer (V5UIWidgets.cpp) wraps each of these in an actual CommonUI/UMG widget that constructs its tree procedurally — no designer .uasset required. UV5_UI_ShellWidget (a UCommonActivatableWidget) builds one button per registered screen and one per navigation action, maintains an activatable screen stack with PushScreen / PopScreen, and overrides NativeGetDesiredFocusTarget for gamepad focus; the spec proves it registers ten screens, grows and shrinks the stack, and restores the prior active screen on pop.

Shell, menu, settings#

UV5_UI_MainMenu::BuildMainMenuState (V5UISystems.cpp:415) emits nine entries with online-gated Continue/Bureau HQ/Companion App, a six-slide curated Workshop showcase carousel with a wrapping AdvanceCuratedShowcase, and a twelve-month community spotlight calendar; the widget test confirms the carousel advances to index 1 and wraps backward to 5. UV5_UI_Settings::BuildSettingsForCategory (:533) is not a toggle list — it defines real entries across six categories (Display/Audio/Input/Network/ Accessibility/Privacy) with control types, min/max/step ranges, per-cell flags on the eight aim/difficulty accessibility settings, and bPrivacyCritical flags on do-not-sell, DSAR export, and under-13 controls. The settings widget renders one tab per category and the matching control widget per declared control type.

HUDs, dialogue wheel, Mind Palace, photo mode#

UV5_UI_HUDWidgetBase resolves a per-cell route through the mode router, asks the shell for a HUD model, and mounts a meter strip, a quick-action bar, and conditional sub-panels; the seven launch HUD subclasses supply only their route. The V5.UI.Widgets.HUDs spec asserts the Frontier HUD mounts a mount-status panel and tracks horse stamina, the Vice-Squad HUD mounts the investigation notebook, and the Sci-Fi ship HUD mounts the dialogue wheel — the documented per-cell vocabularies, realized as built widget trees. UV5_UI_DialogueWheelWidget lays spokes radially on a canvas at 360 × i / n degrees offset −90° so spoke 0 sits at the top; the spec proves a four-spoke Hunter wheel places spoke 0 at 0° and spoke 1 at 90° with the Hunter flavor token. AV5_UI_MindPalaceVolumetricRoom distributes one evidence orb per clue on a Fibonacci sphere (golden angle π × (3 − √5), ComputeOrbLayout at :569); the test spawns the actor into a transient UWorld, builds three orbs, and asserts each sits on the room shell at distinct positions. UV5_UI_PhotoMode exposes eleven tools, two video export profiles (5 s silent + 15 s AAC-audio MP4), and twelve shooting locations, with ValidateTier2State (:829) enforcing 48 kHz stereo audio, privacy-scrubbed metadata, all-cell location coverage, and a 12-location floor. The companion-app bridge gates web-view / AR / VTuber surfaces on sign-in and under-13 status and asserts no-raw-camera and no-raw-voice upload, and the localization manifest covers sixteen culture codes.

How it connects (and where it does not yet)#

Presentation sits downstream of gameplay and reads, never writes. The reload montages, hit-react variants, dialogue-wheel cursor, and cinematic-finisher root motion selected by the GAS, combat, and animation layer (./gas-animation-input.md) are what should trigger a dialogue route, a ducking snapshot, a Niagara cue, a Sequencer beat, or a HUD re-route; the HUD view-models read state and push nothing back. The interrogation pressure meters, heist phase banners, and Mind Palace deduction threads these surfaces present originate in ./interrogation-dialogue-and-heist.md, and the consent flags, privacy-scrubbed replay metadata, and telemetry toggles the settings, replay editor, and companion bridge expose are governed by the data and live-ops contracts in ./telemetry-build-and-data.md.

The honest remaining work is uniform and identical in shape to the animation layer's: the math, manifests, and validators are real and tested, and V5UI already instantiates live engine widgets — but the authored .uasset content (MetaSound graphs, Niagara systems, level sequences, designer WBP skins), the plugin links for audio and cinematics, and the final emission calls (Niagara spawn, LevelSequence play, MetaSound playback) are the pending integration. These are shippable units awaiting a call site, a plugin link, and authored content, not stubs — every decision they make is computed, deterministic, and pinned to a known-correct value.