GregOrigin - OmniWalk: Arbitrary Gravity & Surface Adhesion Framework

Watch the promo video
Read the manual

OmniWalk is a high-performance C++ middleware framework for Unreal Engine 5.4+ that delivers "Impossible Locomotion." Designed to replicate the high-fidelity magnetism found in titles like Ratchet & Clank and Dead Space, it allows any character to traverse arbitrary geometry — walls, ceilings, pipes, and planets — with zero technical friction.

While UE5.4 introduced native multi-directional gravity, OmniWalk solves the remaining "showstopper" problems: camera gimbal-lock, control inversion, triangle-normal jitter, and complex input remapping.

🚀 The "Zero-Config" unified component

Unlike competing frameworks that require rebuilding your character from a specific parent class, OmniWalk Pro features a unified component architecture.

  • Drop-In Integration: Drag the OmniWalkPro component onto any ACharacter (Pawn, MetaHuman, Synty, etc.).

  • Auto-Hijack Logic: Upon BeginPlay, the component automatically configures Pawn settings (Yaw usage, floor angles), injects a Camera Stabilizer, and intercepts the Input Buffer to project world-space movement onto local surface planes.

🧠 Key Technical USP's

  • Native 5.4+ Gravity Integration: Leverages the re-designed CharacterMovementComponent gravity architecture for frame-perfect physics — not forces-based hacks.

  • Gimbal-Free Camera Solver: A custom C++ Camera modifier resolves the "Euler Singularity." Mouse/Stick look remains intuitive and non-inverted, even when standing upside down on a ceiling.

  • Arbitrary Surface Adhesion: No Volumes required. Walks on any StaticMesh, DynamicMesh, or Landscape normal via optimized trace-averaging.

  • Input Projection Technology: Automatically "steals" world-space movement input and flattens it against the current surface normal, preventing the character from becoming "stuck" against vertical walls.

  • Slate Telemetry Debugger: A dedicated Editor window (Window > OmniWalk Debugger) provides real-time telemetry on gravity vectors, alignment strength, and trace hits.

🛠 Technical Specifications

  • Performance: All core logic is written in C++ and executes in TG_PrePhysics, ensuring zero latency between surface detection and movement integration. Requires the Enhanced Input plugin to be enabled.

  • Orientation Math: Uses Quaternions (QInterpTo) and Slerp-normalization to handle 360-degree transitions without gimbal flips.

  • Procedural Demo Included: Includes a C++ Helix-Generator that constructs "impossible" walking paths at runtime to demonstrate system stability across extreme centripetal forces.

📋 Package Contents

  • Runtime Module: Core Adhesion Component, Camera Stabilizers, Input Hijacker, and World Subsystem.

  • Editor Module: Slate UI Telemetry and Debugging tools.

  • Source Code: Fully commented C++ code.

  • Example Content: Procedural demo level and a "Zero-Touch" implementation guide.

Please take note of the correct setup of this plugin, especially on UE 5.7:




Hi how we get the character to stop strafing?

Hi there, it is done by the Orient Rotation toggle on the OmniWalk component. An update to facilitate it all is coming soon btw.

UnrealEditor_MDUJd226Rk

1 Like

Other settings or assets can also hijack Mouselook from OmniWalk. By default, IMC_Default should be set like this:

Updates and bugfixes are continuous for this plugin, and new features are expected to be added, including vertical wall sliding and wall-to-wall jumps.
An update was submitted today. Thanks for reading.

0.4 Changelog

Setup Wizard (2026-04-23)

  • Reworked the Setup Wizard from an example-level wrapper into a real onboarding tool with separate Project Setup and Example Tools modes.
  • Added current-project audit coverage for Enhanced Input, starter asset presence, current-level GameMode readiness, and selected Character actor readiness.
  • Added starter Blueprint planning, path validation, and non-destructive creation for:
    • BP_OW_PlayerController
    • BP_OW_FirstPersonCharacter
    • BP_OW_ThirdPersonCharacter
    • BP_OW_FirstPersonGameMode
    • BP_OW_ThirdPersonGameMode
  • Added relinking so generated GameMode Blueprints automatically point to the generated Character and Controller Blueprints.
  • Added one-click actions to assign the generated first-person or third-person GameMode to the current level.
  • Added selected-Character tagging workflow for OmniWalk.Enabled, including cleanup of blocking tags such as OmniWalk.NoAutoInject, OmniWalk.Disabled, and OmniWalk.Ignore.
  • Added direct actions to open the manual, support page, and Fab listing from the wizard.

Files:

  • Plugins\OmniWalk\Source\OmniWalkEditor\Public\SOmniWalkSetupWizard.h
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\SOmniWalkSetupWizard.cpp
  • Plugins\OmniWalk\Source\OmniWalkEditor\Public\OmniWalkSetupWizardUtility.h
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkSetupWizardUtility.cpp
  • Plugins\OmniWalk\Source\OmniWalkEditor\OmniWalkEditor.Build.cs

Example Tools Safety + Scope

  • Split optional demo-content actions out of onboarding so the example workflow is clearly separate from real project setup.
  • Made the example asset root configurable instead of hardcoding everything to /Game/OmniWalkExamples.
  • Added example asset preview and root-path validation before create, rebuild, or cleanup actions run.
  • Reworked cleanup and rebuild so they only touch the managed generated assets:
    • OW_Example
    • BP_OW_CreateExampleLevel
  • Stopped deleting the entire target folder during cleanup or rebuild, which preserves unrelated assets placed in the same directory.
  • Kept the legacy no-argument utility entry points as wrappers around the new path-aware implementation.

Files:

  • Plugins\OmniWalk\Source\OmniWalkEditor\Public\OmniWalkExampleLevelUtility.h
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkExampleLevelUtility.cpp
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\SOmniWalkSetupWizard.cpp

Docs + Marketplace Metadata Sync

  • Updated the docs to send users through Window -> OmniWalk -> OmniWalk Setup Wizard instead of the removed direct example-level commands.
  • Replaced stale auto-inject guidance with the current OmniWalk.Enabled tag.
  • Corrected the example setup docs to reference AOmniWalkFirstPersonCharacter instead of the stale AOmniWalkExampleCharacter claim.
  • Updated plugin metadata URLs so the manual, support page, creator site, and Fab listing all resolve correctly.
  • Updated the editor menu tooltip copy so it matches the new setup-first workflow.

Files:

  • Plugins\OmniWalk\Docs\index.html
  • Plugins\OmniWalk\OmniWalk.uplugin
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkEditor.cpp

Automation + UE 5.7 Verification

  • Added editor automation coverage for content-path validation and starter asset plan drift.
  • Added KismetCompiler as an editor dependency for starter Blueprint configuration and compile steps.
  • Fixed UE 5.7 Slate/API compatibility issues discovered during live verification:
    • SWrapBox now uses UseAllottedSize
    • LeftChopInline now uses EAllowShrinking::No
  • Verified OmniWalkDevEditor builds successfully against UE 5.7.
  • Verified both setup-wizard automation tests pass:
    • OmniWalk.Editor.SetupWizard.PathValidation
    • OmniWalk.Editor.SetupWizard.StarterPlan
  • Observed a non-blocking Unreal warning that Visual Studio 2026 toolchain 14.50 is not the engine’s preferred compiler version, but the build completed successfully.

Files:

  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkSetupWizardTests.cpp
  • Plugins\OmniWalk\Source\OmniWalkEditor\OmniWalkEditor.Build.cs
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\SOmniWalkSetupWizard.cpp
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkSetupWizardUtility.cpp
  • Saved\AutomationReports\SetupWizard\index.json
  • Saved\Logs\OmniWalkDev.log

Input + Movement Fixes

  • Added bUseInternalInputFix to gate internal remapping and avoid double-mapping.
  • Added one-time warning when input already appears gravity-plane-aligned.

Files:

  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkPro.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkPro.cpp

Blueprint Helper Node

  • Added UOmniWalkBlueprintLibrary::AddGravityRelativeMovement for gravity-relative input.
  • Added one-time warning when used without AOmniWalkPlayerController.

Files:

  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkBlueprintLibrary.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkBlueprintLibrary.cpp

Example Runtime Classes

  • Added AOmniWalkExampleCharacter with gravity-relative input wiring.
  • Added AOmniWalkExampleGameMode that uses OmniWalk controller + example pawn.

Files:

  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkExampleCharacter.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkExampleCharacter.cpp
  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkExampleGameMode.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkExampleGameMode.cpp

Editor Utility: Example Level Creation

  • Added editor utility UOmniWalkExampleLevelUtility for generating example maps.
  • Auto-creates Editor Utility Blueprint: /Game/OmniWalkExamples/BP_OW_CreateExampleLevel.
  • Added toast notifications for success/failure.
  • Added cleanup + rebuild workflows with confirmation dialogs.

Files:

  • Plugins\OmniWalk\Source\OmniWalkEditor\Public\OmniWalkExampleLevelUtility.h
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkExampleLevelUtility.cpp

Editor Menu Integration

  • Added menu entries under Window -> OmniWalk:
    • Create OmniWalk Example Level
    • Create Example Level and Open
    • Remove OmniWalk Example Assets
    • Rebuild Example Level and Open

File:

  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkEditor.cpp

Editor Module Dependencies

  • Added dependencies for editor utility creation and scripting.

File:

  • Plugins\OmniWalk\Source\OmniWalkEditor\OmniWalkEditor.Build.cs

Documentation

  • Added and expanded example setup instructions with menu shortcuts.

File:

  • Plugins\OmniWalk\Resources\ExampleMap_Instructions.md

Wall Movement + Dismount Controls

  • Added camera upright blending on wall surfaces to stabilize WASD movement.
  • Added dedicated dismount system with optional Jump-hold trigger, default gravity return, and configurable impulses/cooldowns.
  • Added OmniWalkPro auto-binding for Dismount input with Enhanced Input asset support and legacy fallback.
  • Added Blueprint helper node for OmniWalk Request Dismount.
  • Added default Dismount mappings in DefaultInput.ini.
  • Enabled dismount debug message on the example character via bDebugDismount.
  • Added corner stability fix with surface-loss grace window to prevent falling off at wall transitions.
  • Added surface tracing throttles and adaptive multi-point sampling to reduce CPU/trace costs when stable.
  • Added large-angle transition smoothing with a minimum transition time for 90° wall pivots.
  • Added optional wall sliding with acceleration-based control and configurable slide speed.

Files:

  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkPlayerController.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkPlayerController.cpp
  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkPro.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkPro.cpp
  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkBlueprintLibrary.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkBlueprintLibrary.cpp
  • Plugins\OmniWalk\Source\OmniWalk\Public\OmniWalkExampleCharacter.h
  • Plugins\OmniWalk\Source\OmniWalk\Private\OmniWalkExampleCharacter.cpp
  • Config\DefaultInput.ini
  • Plugins\OmniWalk\Resources\ExampleMap_Instructions.md

Setup Wizard & UI

  • Built a user-friendly OmniWalk Setup Wizard using a bespoke Slate widget (SOmniWalkSetupWizard).
  • Added “Simple Mode” with one-click “Quick Setup” for generating the example environment.
  • Added “Advanced Mode” with granular controls for creating, rebuilding, and cleaning up example assets independently.
  • Unified cluttered example level commands under a single OmniWalk Setup Wizard entry in the Window -> OmniWalk menu.
  • Registered the Setup Wizard as a dockable/floating Nomad Tab Spawner.

Files:

  • Plugins\OmniWalk\Source\OmniWalkEditor\Public\SOmniWalkSetupWizard.h
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\SOmniWalkSetupWizard.cpp
  • Plugins\OmniWalk\Source\OmniWalkEditor\Public\OmniWalkEditor.h
  • Plugins\OmniWalk\Source\OmniWalkEditor\Private\OmniWalkEditor.cpp

0.4 introduced some issues, 0.4.1 now corrects those.

Changelog: 0.4.1 (1 May 2026)

Fixed

  • Fixed Spider Walk traversal on the OmniWalk character so it now wraps across sharp 90-degree wall ledges instead of unpredictable behavior.
  • Improved convex-edge probing to support wall-to-top and top-to-down face transitions, not just floor-to-wall cases.
  • Fixed Setup Wizard result handling so Project Setup and Example Tools report their own action status independently.
  • Fixed Setup Wizard auto-injection tagging so opted-out actors are skipped and preserve tags such as OmniWalk.Disabled, OmniWalk.Ignore, and OmniWalk.NoAutoInject.
  • Fixed showcase demo map generation so OW_Example is playable immediately after creation.
  • Fixed generated showcase runtime setup to include OmniWalkFirstPersonGameMode, a PlayerStart, and AOmniWalkShowcaseLevel.
  • Fixed legacy generated-map cleanup so old native demo generator actors and incompatible placed pawn actors are removed from managed example levels.
  • Fixed showcase planetoid behavior by giving the planetoid collision and a matching point-gravity volume.
  • Fixed trigger-zone demo sizing by adding configurable trigger collision box extents and applying them in the showcase.
  • Fixed Surface Response showcase wiring by assigning physical materials to generated response strips and giving the example character a surface-response component.
  • Fixed Zero-G showcase support by adding UOmniWalkZeroGComponent to the example character and routing movement input into thruster input while Zero-G is active.

Changed

  • Reworked the generated showcase map into a guided, low-pressure feature tour rather than a challenging obstacle course.
  • Expanded the showcase route to introduce major systems in sequence:
    • Core surface adhesion.
    • Wall/ceiling traversal.
    • MagBoot states.
    • Spider Walk convex ledges.
    • Point-gravity planetoid traversal.
    • Directional gravity rooms.
    • Trigger zones.
    • Zero-G pads and magnetized exits.
    • Surface Response material strips.
    • Finale climb/summit.
  • Made showcase progression easier with wider paths, larger landings, clearer labels, shorter climbs, broad steps, rest platforms, catch decks, and oversized Zero-G pads.
  • Replaced the spider-walk pyramid-style demo with a readable wall/top/down training block with rails and visual markers.
  • Reworked the planetoid section with connected ascent/descent ramps and a wide equatorial ring road.
  • Rebalanced the Zero-G chamber with closer platforms, larger pads, visible entry/exit affordances, side posts, and a low recovery deck.
  • Shortened and widened the finale route to make completion reliable during a first playthrough.
  • Updated generated surface-strip labels to match the actual response multipliers.

Added

  • Added automated coverage for generated showcase map creation.
  • Added automated coverage for showcase runtime plumbing.
  • Added automated checks that the example character includes Surface Response and Zero-G support.
  • Added tests covering Setup Wizard tag persistence and opt-out behavior.
  • Added documentation for the new guided showcase route, easier demo tuning, Zero-G component behavior, Surface Response showcase setup, trigger-zone extents, and Setup Wizard opt-out tags.

Documentation

  • Updated Plugins/OmniWalk/Docs/Manual.html with:
    • Setup Wizard opt-out tag behavior.
    • Separate Project Setup vs Example Tools result reporting.
    • New guided showcase map description and route diagram.
    • Easier showcase progression notes.
    • Updated Spider Walk ledge traversal behavior.
    • Updated planetoid gravity-volume behavior.
    • Zero-G input/thruster behavior.
    • Surface Response demo material/table behavior.
    • Trigger-zone configurable collision extents.

Verification

  • Ran Automation RunTests OmniWalk.Editor.SetupWizard successfully.
  • Result: 7 tests passed.

Update video: 0.4

0.5.0 update, 2026-05-28 :person_running: :footprints:

New Additions :sparkles:

  1. :gear: Enhanced Input Auto-Injector & WASD Project-Fix ( HandleAutoConfigureEnhancedInput ):
    • Scans your active editor actor selection or Content Browser Blueprint selections.
    • Auto-enables the internal input remapping fix ( bUseInternalInputFix = true and bProjectGravityFromSurface = true ) on the UOmniWalkPro default components. This allows existing characters with legacy XY input vectors to seamlessly walk on walls instantly without any blueprint graph changes.

  2. :rock: Physics Collision Profile & Level Mesh Auditor ( HandleAuditLevelCollisions / HandleFixLevelCollisions ):
    • Scans the active level for Static Meshes configured with NoCollision that would otherwise cause surface traces to fail.
    • Provides a “One-Click Fix” to repair those meshes, setting their collision status to QueryAndPhysics and assigning a standard BlockAll profile so wall climbing is perfect.

  3. :test_tube: Dynamic Material Surface Response Table Configurator ( HandleConfigureResponseTable ):
    • Auto-generates, duplicates, and saves a default showcase UOmniWalkSurfaceResponseTable asset in your starter directory.
    • Auto-binds and links the Response Table to the UOmniWalkSurfaceResponse component of all selected Characters or Blueprint CDOs.

  4. :person_running: Locomotion Presets Injector ( HandleApplyLocomotionPreset ):
    • Adds an elegant Slate dropdown menu allowing you to instantly apply optimized physics presets to selected character/Blueprint UOmniWalkPro components:
    • Spider Climber: Optimized for 90° convex ledges, sticky transitions, and fast ceiling walking.
    • Wall Runner: Tuning for high-speed wall sliding and input-based braking/hanging.
    • Zero-G Float: Configured for volume-based orbital flight (stops projecting gravity from surface meshes).
    • Standard Adhesion: Standard stable C++ defaults.

  5. :bar_chart: Direct Telemetry Debugger Launcher ( HandleLaunchTelemetryDebugger ):
    • Adds a direct visual shortcut button to instantly invoke the live SOmniWalkDebugger nomad tab next to your active editor viewport.

Overhauls and Fixes :construction_worker:

CDO Constructor Error Resolution: Fully refactored the skeletal mesh and animation asset loading in AOmniWalkThirdPersonCharacter out of the CDO static constructor ( ConstructorHelpers::FObjectFinder ) and into a dynamic, safe load block inside BeginPlay() using FPackageName::DoesPackageExist . This completely resolved severe red CDO
constructor errors on startup.
Look Action Skipping Safeguard: Upgraded AOmniWalkPlayerController 's IA_Look package resolution to use FPackageName::DoesPackageExist path checks before loading UInputActions from disk, eliminating all noisy SkipPackage package streaming warnings.
Spider Walk (Convex Traversal) System Overhaul: Overhauled the convex edge detection algorithm in UOmniWalkPro to resolve slow-movement, zero-input, and high-speed transition dismount bugs:
• Added Projected Actor Forward Fallback to maintain surface tracking when input and velocity project to zero on the surface plane.
• Replaced single far sweeps with Dual Over-Edge Probes (close sweep at CapsuleRadius + 15cm and far sweep at CapsuleRadius + FMath::Min(ConvexCheckDistance, 60.0f) ) to guarantee stable ledge sweeps at any velocity.
• Relaxed the transition boundary check limit AheadDot from -CapsuleRadius * 0.75f to -CapsuleRadius * 1.5f to prevent premature dismount rejection during sprinting and sliding.
Coyote Time & Setup Wizard Unit Testing:
• Added public, Blueprint-callable getters GetCoyoteTimer() and WasOnSurface() to AOmniWalkExampleCharacter to facilitate robust test verification.
• Refactored the CoyoteTime locomotion unit tests in OmniWalkSetupWizardTests.cpp to use Direct C++ Interface Invocations via Cast (e.g. Cast ), bypassing script/headless VM event routing constraints on pure C++ instances in offline editor tests.
• 100% pass rate on all 9 automation tests with zero warnings/errors in the test runner.

:notebook_with_decorative_cover: A dedicated online manual to the vastly improved OmniWalk Setup Wizard is now available:

Hello! Sir,may i ask how to remove the arrow markings on the character’s body?

1 Like

Sounds like visual debug is on. Please find it on the Details panel of the character (under OmniWalk), and tick off Debug.

0.5.1 update, 2026-06-11 :up_right_arrow:

CPU Profiling & Insights Integration

  • Unreal Insights Integration.
  • Hot Path Tracing: Injected TRACE_CPUPROFILER_EVENT_SCOPE macros into high-frequency loops (UOmniWalkPro::TickComponent and UOmniWalkPro::DetectSurfaceAsync) to allow developers to accurately monitor the ms budget consumed by OmniWalk’s surface tracing and gravity interpolation logic.
  • Physics Field Validation: Re-checked the “Gravity Wake” localized physics displacement tool, negating the need for a new physics system.
  • Setup Wizard UX Improvements: Overhauled the SOmniWalkSetupWizard slate interface for improved user onboarding.
    • Implemented “Generate Playable Third-Person Setup” for One-Click onboarding matching the First-Person workflow.
    • Added self-documenting UI Tooltips (ToolTipText) to all Project Setup buttons to clarify background asset generation and GameMode assignment actions.

0.6 update, 2026-06-24 :footprints:

:bookmark: Legend

Symbol Meaning
:red_circle: Critical — breaks gameplay or multiplayer
:orange_circle: Conflict — two systems fighting over the same state
:yellow_circle: Logic — incorrect or dead behavior
:blue_circle: Gap / Quality — missing, degraded, or untidy
:sparkles: New — added API or capability
:recycling_symbol: Changed — refactor / rename
:white_check_mark: Validated — confirmed by build / test

:adhesive_bandage: Surface, Gravity & Multiplayer Hardening

:shield: Networking & Multiplayer

  • :red_circle: Wall-slide no longer disconnects clients. Server_SetWallSliding_Validate rejected the
    documented -1 “keep current speed” sentinel, and a failed RPC validation closes the client’s
    connection
    , so toggling wall-slide on a client instantly kicked the player. Validation now
    accepts the sentinel and only rejects non-finite / over-cap values. → UOmniWalkPro
  • :red_circle: Gravity now syncs to all players. State went out via a Client RPC (owner-only), so
    simulated proxies never updated. Switched to NetMulticast (Multicast_SyncGravityState);
    simulated proxies are now driven by replication instead of fighting it with local traces.
    UOmniWalkPro
  • :recycling_symbol: Mag-boot state applies locally on replication via new ApplyMagBootState(), so the
    handler no longer bounces a Server_ RPC on proxies (warn-spam + drop). → UOmniWalkPro

:magnet: Gravity & Surface Walking

  • :orange_circle: Unified gravity-override channel. Gravity volumes and trigger zones now hold their gravity
    even while the character is grounded (previously clobbered every tick by surface detection) and
    decay shortly after the character leaves. → AOmniWalkTriggerZone, AOmniWalkSplineVolume, UOmniWalkPro
  • :orange_circle: Killed per-frame client warning spam from external gravity drivers — the override path is
    silently authority-only and replicates the result back. → UOmniWalkPro
  • :yellow_circle: Adhesion gate fixed. A tautological || SpeedToward > 0.0f made “needs adhesion” always
    true; adhesion now engages only when falling or not already snapping into the surface. → UOmniWalkPro
  • :blue_circle: Async traces no longer disable wall climbing. Async mode resolved only the floor; wall +
    convex-edge (spider-walk) detection now runs each frame via shared DetectWallOrConvex(). → UOmniWalkPro
  • :yellow_circle: Gravity-volume containment no longer depends on component visibility (which diverged
    between editor and packaged/runtime-spawned volumes). Bounds are chosen by GravityType.
    AOmniWalkGravityVolume

:clapper_board: Cinematic & :rocket: Zero-G

  • :orange_circle: Cinematic mode suspends the walker and transitions start from the
    current surface normal, not world-up — no snap when starting on a wall. → UOmniWalkCinematic, UOmniWalkPro
  • :orange_circle: Zero-G flight suspends the walker so it stops fighting 6DOF orientation (mag-boot Off
    alone didn’t). → UOmniWalkZeroGComponent

:gear: Configuration & :broom: Quality

  • :blue_circle: UOmniWalkPro seeds tunables from UOmniWalkSettings
    in its constructor (per-instance / Blueprint edits still win). → UOmniWalkPro, UOmniWalkSettings
  • :blue_circle: Trace channels are configurable (ECC_WorldStatic default), replacing hard-coded
    ECC_Visibility. → UOmniWalkHoverComponent, UOmniWalkFootIKComponent
  • :blue_circle: Foot-IK dead code removed (discarded projection + duplicated if/else). → UOmniWalkFootIKComponent
  • :sponge: Removed a duplicated include / copyright block in OmniWalkPro.cpp.
  • :white_check_mark: Automation test harness added: covers the surface “wall-like” classifier and
    replication-state equality (run via OmniWalk. in the Automation window). → OmniWalkProTests.cpp

:sparkles: New API

// Gravity override: external drivers steer gravity without being clobbered by surface detection.
void  UOmniWalkPro::SetGravityOverride(FVector NewUp, bool bImmediate = false, float HoldSeconds = 0.25f);
void  UOmniWalkPro::ClearGravityOverride();
bool  UOmniWalkPro::IsGravityOverrideActive() const;

// Full suspend — cutscenes / zero-G yield all per-tick control to an external controller.
void  UOmniWalkPro::SetMovementControlSuspended(bool bSuspended);
bool  UOmniWalkPro::IsMovementControlSuspended() const;

// Pure, testable surface classifier.
static bool UOmniWalkPro::IsSurfaceWallLike(const FVector& Normal, const FVector& Up, float Threshold);

:recycling_symbol: Renamed

  • Client_SyncGravityStateMulticast_SyncGravityState (Client, ReliableNetMulticast, Unreliable).

:warning: Known limitation

  • :globe_with_meridians: While the walker is suspended (cinematic / zero-G), the per-tick multicast sync is skipped,
    so a networked cinematic gravity flip won’t auto-replicate to observers. Single-player /
    standalone is unaffected.

:toolbox: Upgrade notes

  • :repeat_button: Clean rebuild required: RPC / UFUNCTION signatures changed (UHT regenerates reflection).
  • :puzzle_piece: No content/asset changes; existing Blueprints keep working.

:file_folder: Touched: OmniWalkPro.{h,cpp}, OmniWalkTriggerZone.cpp, OmniWalkSplineVolume.cpp,
OmniWalkCinematic.cpp, OmniWalkZeroGComponent.cpp, OmniWalkGravityVolume.cpp,
OmniWalkFootIKComponent.{h,cpp}, OmniWalkHoverComponent.{h,cpp}, OmniWalkProTests.cpp (new).

Please note that the plugin is under heavy development, and cannot be guaranteed to work in all use cases until it hits the 1.0.0 milestone.
The 0.6.0 update is still under Fab review/vetting at the time of this writing.

Do you have any advice on installing this plugin for Linux users? I’m on UE 5.6 and in the past once whenever i purchased or downloaded a plugin, I rebuilt the plugin from its source files to make it compatible with the editor which I built from source.

I downloaded the plugin using Lutris (since epic games launcher doesn’t work natively on Linux) and that worked, but there aren’t any source files, so i’m unsure how to get it working on my Linux machine. I’m on Arch if that helps any.

1 Like

@smbmaster99 Apologies for the delay. (There was an accident in my family, delaying work things in general.) An update is on the way.

0.6.5 update, 2026-08-29

:hammer_and_wrench: Update contains a breaking Blueprint API change (see :warning: below).

:test_tube: Tests: 15/15 pass. :white_check_mark:
:globe_with_meridians: Engines validated: UE 5.5.4, 5.6.1, 5.7.4, 5.8.2


:collision: Crash, Hang & Data-Loss

  • :red_circle: Fixed an out-of-bounds crash in the hover vehicle. TickComponent looped a hardcoded
    i < 4 while indexing TraceOffsets[Index], an EditAnywhere array. Any craft configured with
    fewer than four suspension points (a bike, a tripod) read past the end and crashed on first tick.
    The loop now follows TraceOffsets.Num(), and an empty array disables the component with a
    warning instead of faulting. → UOmniWalkHoverComponent
  • :red_circle: Fixed an editor/game hang in the surface nav volume. BuildGraph stepped a sample loop with
    X += VoxelSize; VoxelSize had no clamp, so 0 (or a negative) never terminated. Now clamped
    by property metadata and at runtime; metadata does not apply to Blueprint writes or older
    serialised assets. → AOmniWalkSurfaceNavVolume
  • :red_circle: Nav graph generation is no longer quadratic. Node de-duplication linear-scanned every node
    already generated, inside a triple voxel loop × 6 directions; edge building was a full O(N²) pair
    sweep with up to 3 synchronous line traces each; all on the game thread at BeginPlay. Replaced
    with a uniform spatial hash; both passes are now near-linear. Added MaxNodes (default 20 000),
    a pre-build size warning, and a warning when a graph is built at runtime rather than in-editor.
    AOmniWalkSurfaceNavVolume
  • :red_circle: A-star no longer degenerates. The open set was a TArray linear-scanned for the minimum with
    TArray::Contains for membership; O(N) per expansion, no closed set, so nodes were re-expanded.
    Now a binary heap with a TBitArray closed set and hash-accelerated nearest-node lookup.
    AOmniWalkSurfaceNavVolume::FindPath

:shield: Networking & Multiplayer

  • :red_circle: Replicated surface normals were being destroyed on the wire. FOmniWalkReplicationState
    used FVector_NetQuantize, which serialises via SerializePackedVector<1, 20>scale 1, zero
    decimal places
    . Every component of a unit normal rounded to -1, 0 or 1: a wall normal of
    (0.6, 0.8, 0) arrived as (1, 1, 0), failed the receiving IsNormalized() check, and was
    discarded with a warning. Simulated proxies therefore never received correct gravity for any
    non-axis-aligned surface. Switched to FVector_NetQuantizeNormal (16 bits per component across
    [-1,1]), pinned by a new automation test so it cannot be silently downgraded again.
    FOmniWalkReplicationState
  • :red_circle: Dedicated-server auto-injection was completely broken. InitializeTaggedActors returned early
    on NM_DedicatedServer, so the server never created the component. Clients injected locally and
    fired Server_* RPCs at a component that did not exist server-side, with no authority anywhere to
    drive gravity. The bail-out is removed; injection now runs wherever the component can do work —
    authority, or any locally controlled pawn. → UOmniWalkSubsystem
  • :orange_circle: Autonomous proxies no longer fight their own prediction. Client-side interpolation was gated on
    GetOwnerRole() < ROLE_Authority, which includes ROLE_AutonomousProxy — so the local player’s own
    pawn blended toward the 10 Hz server state and ran local detection every frame. Interpolation is
    now simulated-proxy only; autonomous proxies keep their prediction and adopt only the authoritative
    booleans. → UOmniWalkPro
  • :orange_circle: Stopped a per-frame wall-slide RPC storm. The per-tick auto-enable called SetWallSliding(true)
    every frame while on a wall; on a client that re-sent Server_SetWallSliding until the 10 Hz
    multicast echoed back; most rejected by the rate limiter, each with a warning. A request latch now
    sends once per state change. → UOmniWalkPro
  • :blue_circle: Gravity state is no longer broadcast unconditionally. Multicast_SyncGravityState fired every
    100 ms per authoritative pawn regardless of change; a stationary character cost the same bandwidth
    as a moving one, multiplied by pawns × clients. The struct’s operator== existed but was never
    called in production
    ; its only consumer was a unit test. It is now the send-side change check,
    with a tolerance coarser than the wire quantisation. → UOmniWalkPro

:magnet: Gravity & Surface Walking

  • :yellow_circle: Rotating-platform gravity tracking used the wrong delta. The code computed
    Current * Previous.Inverse(). FTransform composes A * B as “apply A then B” — the
    Relative * ParentWorld idiom — so that yields the base’s local-frame delta, which matches the
    world delta only when the platform’s rest rotation is identity. A tilted or tumbling planetoid drifted
    the surface normal. Corrected to Previous.Inverse() * Current. → UOmniWalkPro
  • :yellow_circle: Async traces no longer jitter on walls. OnAsyncTraceComplete wrote the floor-only result
    into the same cache the tick then overwrote with the wall/convex-inclusive result, so the two clobbered
    each other on alternate frames. The async floor result now has its own storage. Also fixed a stale-handle
    path that cleared the pending flag early and could open a second overlapping trace. → UOmniWalkPro
  • :yellow_circle: Spline gravity volumes now use the spline as their bounds. Containment routed Point and Spline
    through a sphere centred on the actor (500 cm default), so a tube of any real length was mostly outside
    its own containment test and gravity cut out along most of it. Spline volumes now measure distance to
    the spline, via a new SplineTubeRadius. → AOmniWalkGravityVolume
  • :yellow_circle: Gravity volume priority is honoured at runtime. Volumes were sorted only at registration, so any
    runtime change to Priority silently had no effect. The highest-priority containing volume is now
    chosen by inspection, and stale entries are skipped. → UOmniWalkSubsystem
  • :orange_circle: Mag-Boot presets no longer destroy your tuning. Standard hard-wrote AdhesionForce = 3500,
    bAutoEnableWallSlide = true and bWallSlideResistsInput = true — so a Blueprint that set
    AdhesionForce = 8000 lost it the first time a trigger zone or Zero-G transition touched
    MagBootState. The component now captures your values once and Standard restores them;
    MagLock and Hover are multipliers on your baseline. Defaults reproduce the previous absolute
    values exactly at stock adhesion, pinned by a test. → UOmniWalkPro
  • :blue_circle: Physics field no longer double-counts gravity, and its MaxAffectedObjects cap is now
    distance-ranked. Overlap order is not stable between queries, so a naive “first N” cap churned the
    affected set and produced spurious Enter/Leave events every sample.
    UOmniWalkHoverComponent, UOmniWalkPhysicsField

:bone: Animation & Foot IK

  • :red_circle: Fixed a data race in the Foot IK anim node. UpdateInternal called
    OwnerActor->FindComponentByClass<...>() every frame — but it runs on the animation worker thread
    when multi-threaded animation update is enabled, the engine default. All owning-actor access moved to
    PreUpdate (game thread), with the component resolved once and cached instead of an O(n) scan per frame.
    FAnimNode_OmniWalkFootIK
  • :yellow_circle: Fixed the world-to-component rotation conversion. The code wrote World * Comp⁻¹. FQuat
    composes as (A * B).RotateVector(v) == A.RotateVector(B.RotateVector(v)), so the component-space
    equivalent is Comp⁻¹ * World. The original was correct only when the mesh’s component rotation was
    identity — which, for a character on walls and ceilings, it essentially never is. Foot rotation IK was
    wrong on every non-upright surface. → UOmniWalkFootIKComponent
  • :blue_circle: PelvisAlpha is no longer dead. It was computed every tick and never read, so IK snapped fully on
    the frame it was enabled. The node now scales its entire contribution by it, and the component eases the
    weight back out on disable. → UOmniWalkFootIKComponent, FAnimNode_OmniWalkFootIK
  • :blue_circle: Bone transforms are sorted before submission. The pose blend requires ascending compact-pose index;
    pelvis-before-feet is a property of the skeleton’s ordering, not a guarantee for arbitrary rigs.
    FAnimNode_OmniWalkFootIK

:clapper_board: Cinematic & :rocket: Zero-G

  • :yellow_circle: 180-degree gravity flips no longer degenerate. The transition linearly lerped between normals;
    between near-antiparallel vectors that passes through (or near) zero, which normalises to nothing — so a
    ceiling flip, the headline use case, snapped instead of animating. Replaced with arc interpolation,
    including an explicit antiparallel branch where FindBetweenNormals has no unique answer.
    UOmniWalkCinematic
  • :yellow_circle: Zero-G rotation no longer spins forever. Angular damping and integration lived inside
    AddThrusterInput, so they only ran while the player held the stick — release input and the character
    span indefinitely. Both moved to TickComponent. → UOmniWalkZeroGComponent
  • :yellow_circle: Zero-G drag is now framerate-independent. Linear (*= 0.99) and angular (*= 0.95) damping were
    fixed per-tick multipliers, so a character decelerated several times faster at 120 fps than at 30. Now
    exponential in DeltaTime, exposed as LinearDamping / AngularDamping — defaults reproduce the
    previous feel at 60 fps — plus a new MaxAngularSpeed clamp. → UOmniWalkZeroGComponent
  • :blue_circle: Zero-G magnetise now uses a configurable TraceChannel instead of a hardcoded ECC_WorldStatic, and
    warns instead of silently doing nothing when the owner has no CharacterMovementComponent.
    UOmniWalkZeroGComponent

:video_game: Input, Camera & Example Character

  • :red_circle: Removed unconditional per-frame logging from the example character. HandleMove carried a
    UE_LOG(..., Log, ...) marked “ALWAYS log for debugging” that fired on every input frame — an
    FString format plus a log write per frame in Shipping, since LogOmniWalk is declared with
    compile-time verbosity All. Now behind #if WITH_EDITOR plus the debug switch, at Verbose.
    AOmniWalkExampleCharacter
  • :red_circle: The example character works with any PlayerController again. It hard-required
    AOmniWalkPlayerController::GetGravityRelativeDirection and, failing that, logged at Error
    verbosity every input frame
    and returned — producing zero movement plus an unbounded error flood for
    any buyer using their own controller. It now falls back to
    UOmniWalkBlueprintLibrary::AddGravityRelativeMovement (same math, controller-agnostic) and notes the
    fallback once. → AOmniWalkExampleCharacter
  • :yellow_circle: Fixed inverted handedness in the wall movement basis. The wall branch built
    Cross(Forward, GravityUp) while the ground branch used Cross(GravityUp, Forward) — opposite sign —
    and relied on a camera-forward dot to correct it. Looking straight at a wall, which is the wall-walking
    posture, makes that dot approach zero, so strafe direction flipped unpredictably. The basis is now built
    with the correct handedness up front and aligned against the well-conditioned camera right.
    UOmniWalkBlueprintLibrary
  • :orange_circle: The controller no longer hijacks project input. bAutoSetGameInputMode forced
    FInputModeGameOnly and hid the cursor from BeginPlay, breaking any project that starts on a menu;
    and the controller probed the buyer’s own content for a stock IA_Look, then registered its mapping
    context at priority 100 — outranking essentially any project mapping and doubling look input. Both
    are now opt-in (bAutoSetGameInputMode, bAutoDiscoverProjectLookAction, both default false), the
    priority is configurable and defaults to 0, and explicit LookActionAsset /
    LookMappingContextAsset references are supported. → AOmniWalkPlayerController
  • :yellow_circle: Look input survives re-possession. SetupEnhancedLookInput early-returned once the action and
    context existed, so a fresh InputComponent handed over on respawn never got the binding and look input
    silently died. The bound component is now tracked, with bindings cleared before rebinding so handlers
    cannot stack. → AOmniWalkPlayerController
  • :blue_circle: Bounded the look-context retry. Tick polled GetLocalPlayer() every frame forever when no local
    player existed. Now capped at roughly 5 seconds with a single warning. → AOmniWalkPlayerController

:test_tube: Debug Visualisation & Diagnostics

  • :red_circle: Fixed permanently jammed debug HUD text. With the shipped defaults
    (bDebugVisualization = true, DebugDrawDuration = -1), all seven DrawDebugString calls passed -1.
    Verified against engine source: AHUD treats TimeRemaining == -1 as never expires, and
    DrawDebugString passes bSkipOverwriteCheck = true so entries append rather than replace, capped
    at 128 per actor. Every call passed TestBaseActor = nullptr, piling them all onto WorldSettings. At
    5-8 strings per frame the list saturated with frozen, never-expiring labels in under a second, after
    which new state text was silently dropped. → UOmniWalkPro
  • :yellow_circle: DebugDrawDuration now behaves as documented. The header and guide both claimed -1 = one frame,
    0 = disabled. Engine source (GetDebugLineLifeTime: LifeTime > 0 ? LifeTime : DefaultLifeTime) shows
    0 and -1 are identical — one frame — for shapes, and 0 does not disable anything; for HUD text
    the mapping is inverted. The value is now translated per primitive so all three documented values are
    true, and 0 genuinely disables drawing.
    UOmniWalkPro, Docs/DebugVisualizationGuide.md
  • :blue_circle: All debug visualisation now defaults off. UOmniWalkPro, AOmniWalkPatrolPath and
    UOmniWalkSurfacePathFollower shipped with debug drawing enabled — the patrol path at a 5-second
    lifetime, so it accumulated. Six debug properties across the plugin are now consistently false, seeded
    from new Project Settings.
  • :blue_circle: Convex-traversal probes honour the configured lifetime instead of a hardcoded 2 s, which stacked
    roughly 120 primitives per probe at 60 fps while spider-walking. → UOmniWalkPro
  • :blue_circle: Log noise cut for shipped games. 45 diagnostic Log-verbosity calls demoted to Verbose; only 3
    remain — module start/stop and the nav-graph build result. None were stripped in Shipping before, because
    the category is declared with compile-time verbosity All.

:gear: Configuration & :package: Packaging

  • :blue_circle: DefaultOmniWalk.ini had three dead keys and two dead sections — verified by grep, zero code
    references. DefaultSurfaceTraceChannel had no matching property, and the trace channel was never seeded
    from settings at all; [/Script/OmniWalk.OmniWalkSubsystem] and [/Script/OmniWalk.OmniWalkPro] could
    never apply, because neither class is config-backed and ReplicationInterval / bReplicateToAllClients
    did not exist. The file is now a single valid section, every key resolves, and the missing properties were
    added. :warning: Channel values need the ECC_ prefix — a bare WorldStatic fails to import silently.
    UOmniWalkSettings, Config/DefaultOmniWalk.ini
  • :blue_circle: Trigger zones only tick when they have work. Every zone in a level ticked unconditionally; tick is
    now enabled on demand. → AOmniWalkTriggerZone

:large_blue_diamond: Blueprint API

  • :sparkles: 54 tuning properties are now runtime-settable. AdhesionForce, AlignmentSpeed, TraceDistance,
    SurfaceTraceChannel, bControlRotation, bEnableConvexTraversals, bProjectGravityFromSurface and
    more were EditAnywhere only — editable in the details panel but unreachable from Blueprint, so you could
    not ramp adhesion for a power-up or hand rotation to a montage. All are now BlueprintReadWrite.
    UOmniWalkPro
  • :recycling_symbol: 16 const getters changed from BlueprintCallable to BlueprintPure — no more exec pins on
    IsGrounded, GetCurrentSurfaceNormal, IsWallSlidingEnabled, GetDefaultGravityUp,
    GetGravityRelativeDirection, GetCurrentGravityUp and others, so they can be used inline in
    expressions. See :warning: Breaking below.
  • :sponge: A further 13 getters had a redundant BlueprintCallable removed where BlueprintPure was already
    present (AOmniWalkPatrolPath, UOmniWalkCinematic, UOmniWalkAIPatrol, AOmniWalkTriggerZone,
    UOmniWalkSurfaceResponse). These were already pure — no behavioural or pin change.
    The plugin now exposes 30 BlueprintPure getters in total.
  • :sparkles: New Mag-Boot tuning knobs: MagLockAdhesionMultiplier, MagLockGroundFriction,
    MagLockBrakingDeceleration, HoverAdhesionMultiplier, HoverGroundFriction,
    HoverBrakingDeceleration.
  • :sparkles: New properties: SplineTubeRadius (gravity volume); MaxNodes, TraceChannel,
    bBuildGraphAtBeginPlay (nav volume); GravityStrength, bDisableBuiltInGravity (hover);
    MaxAngularSpeed, LinearDamping, AngularDamping, TraceChannel (Zero-G); LookActionAsset,
    LookMappingContextAsset, LookMappingContextPriority, bAutoDiscoverProjectLookAction (controller).
  • :sparkles: New settings: DefaultSurfaceTraceChannel, bDefaultDebugVisualization,
    DefaultDebugDrawDuration, bWatchForRuntimeSpawns. → UOmniWalkSettings

:repeat_button: Lifecycle

  • :blue_circle: Auto-injection is no longer a one-shot snapshot. It ran once, 0.1 s after BeginPlay, so player
    respawns, streamed-in levels and runtime-spawned NPCs were never considered. An optional spawn watcher
    (bWatchForRuntimeSpawns, default on) now injects into anything tagged OmniWalk.Enabled that appears
    later, deferred a tick so possession state is final. → UOmniWalkSubsystem

:white_check_mark: Validation

  • :test_tube: Automation coverage expanded from 2 to 5 core tests — 15 total with the editor suite — now covering
    the replication-normal precision requirement, Mag-Boot preset scaling, and the debug-lifetime mapping.
    Each pins a specific defect fixed above so it cannot regress. → OmniWalkProTests.cpp

  • :globe_with_meridians: Verified on four engine versions with byte-identical plugin source, confirmed by diff -rq:

    Engine Editor Dev Shipping Debug-draw stripped Tests
    UE 5.5.4 :white_check_mark: :white_check_mark: :white_check_mark: 15/15
    UE 5.6.1 :white_check_mark: :white_check_mark: :white_check_mark: 15/15
    UE 5.7.4 :white_check_mark: :white_check_mark: :white_check_mark: 15/15
    UE 5.8.2 :white_check_mark: :white_check_mark: :white_check_mark: 15/15
  • :microscope: Shipping verified at symbol level. dumpbin -symbols across all plugin Shipping objects shows
    zero engine DrawDebug* calls linked, on every engine version — the debug defect above is
    structurally impossible in Shipping. The same objects in an editor build reference DrawDebugLine,
    DrawDebugSphere, DrawDebugPoint, DrawDebugDirectionalArrow and DrawDebugString.

:warning: Breaking

  • :large_blue_diamond: The BlueprintPure conversion breaks existing Blueprint graphs. The 16 genuinely converted
    getters lose their exec pins, so UE recreates those nodes and drops the exec wires through them. Open
    affected graphs and reconnect execution flow around the now-pure getter nodes. This is the reason for the
    minor version bump. The other 13 cleaned-up getters were already pure and are unaffected.
  • :video_game: bAutoSetGameInputMode now defaults to false. If you relied on AOmniWalkPlayerController
    forcing Game-Only input, re-enable it explicitly.
  • :test_tube: bDebugVisualization now defaults to false on UOmniWalkPro, AOmniWalkPatrolPath and
    UOmniWalkSurfacePathFollower. Turn it on per-component, or project-wide via
    Project Settings → Plugins → OmniWalk → Default Debug Visualization.

:toolbox: Upgrade notes

  • :repeat_button: Clean rebuild requiredUPROPERTY / UFUNCTION specifiers changed, so UHT must regenerate
    reflection data.
  • :puzzle_piece: No content or asset changes.