Get it on Fab →

Extension Modules

These components extend OmniWalk beyond its locomotion core. Each is independently optional — add only what your game requires. All modules follow the same attach-and-configure pattern as UOmniWalkPro.

Dependency: All modules require UOmniWalkPro to be on the same actor. Add them alongside it in the actor's component list. No additional module dependencies are needed.

Trigger Zones

AOmniWalkTriggerZone overrides OmniWalk gravity for characters that enter a volume. Unlike AOmniWalkGravityVolume (which affects all OmniWalk characters in range), Trigger Zones support per-actor targeting, four gravity modes, and a priority system that resolves conflicts when multiple zones overlap.

Fixed

Gravity pulls in a fixed world direction. Use for artificial gravity corridors, rotating space stations, or puzzle rooms that flip "down".

Point Attract

Gravity pulls toward the zone's center. Mini-planets, portals, or singularity mechanics.

Point Repulse

Gravity pushes away from the center. Anti-gravity emitters, repulsor fields, interior-of-sphere traversal.

Spline Linked

Delegates gravity computation to a referenced AOmniWalkSplineVolume. Use to combine a custom bounding shape with tube-gravity logic.

Setup

  1. Place an AOmniWalkTriggerZone actor in the level.
  2. Set GravityMode in the Details panel. The relevant sub-property (e.g. FixedGravityDirection) becomes active.
  3. Resize the CollisionShape component to match your zone boundary.
  4. Raise Priority above any overlapping AOmniWalkGravityVolume (which is effectively priority 0). Default is 10.
  5. Choose TargetModeAll, Tag Based, or Specific Actors.

Priority Resolution

When multiple zones overlap, UOmniWalkZonePrioritySubsystem selects the one with the highest Priority value. Tie-breaking is first-registered. A character exiting a high-priority zone automatically falls back to the next registered zone, then to the base AOmniWalkGravityVolume.

Priority Stack Example

AOmniWalkGravityVolume Priority: 0 TriggerZone A Priority: 10 TriggerZone B Priority: 50 ← wins

Properties

PropertyPurposeDefault
GravityModeFixed / PointAttract / PointRepulse / SplineLinkedFixed
FixedGravityDirectionWorld direction when GravityMode is Fixed(0,0,-1)
PriorityHigher wins over overlapping zones10
TargetModeAllOmniWalkCharacters / TagBased / SpecificActorsAll
TargetTagsGameplayTag filter (TagBased mode). Matches Actor.Tags by exact name.
TargetActorsExplicit actor list (SpecificActors mode)
LinkedSplineVolumeSpline to delegate to (SplineLinked mode)
bZoneEnabledRuntime on/off toggletrue

Delegates & API

// Respond to zone entry/exit
TriggerZone->OnActorEnterZone.AddDynamic(this, &AMyActor::HandleEnter);
TriggerZone->OnActorLeaveZone.AddDynamic(this, &AMyActor::HandleLeave);

// Toggle zone at runtime
TriggerZone->SetEnabled(false);

// Query gravity "up" for a world location (useful for preview/AI)
FVector GravUp = TriggerZone->ComputeGravityUpForLocation(MyPawn->GetActorLocation());

Spline Volume

AOmniWalkSplineVolume makes gravity follow the nearest point on a USplineComponent. Characters inside the influence box have gravity pulled toward (or away from) the spline axis, blending in at BlendRadius for smooth entry and exit.

bGravityPointsInward = true

Spline Walk outside tube

bGravityPointsInward = false

Spline Walk inside tube

Setup

  1. Place AOmniWalkSplineVolume in the level.
  2. Edit the Spline component to trace your tube center line.
  3. Resize InfluenceVolume (a Box component) to encompass the playable area.
  4. Set bGravityPointsInward to match your geometry (outside = true, inside = false).
  5. Tune BlendRadius to set the blend-in distance from the spline edge.

Properties

PropertyPurposeDefault
BlendRadiusDistance from spline where gravity blends in (cm)200
GravityStrengthForce magnitude applied to characters (cm/s²)980
bGravityPointsInwardtrue = outside tube, false = inside tubetrue
PriorityPriority vs other gravity volumes5
// SplineLinked: a TriggerZone delegates to this volume
TriggerZone->GravityMode = EOmniWalkTriggerGravityMode::SplineLinked;
TriggerZone->LinkedSplineVolume = MySplineVolume;

// Query gravity direction at any world point (C++ / AI use)
FVector Up = MySplineVolume->GetGravityUpForLocation(WorldPos);

Zone Priority System

UOmniWalkZonePrioritySubsystem is an automatic game subsystem — no setup required. It maintains a runtime registry of all active AOmniWalkTriggerZone actors and resolves which zone applies to each character when overlaps conflict.

1. Register Zone enters world
2. Overlap Actor enters volume
3. Resolve Highest priority wins
4. Fallback Exit → next zone or default
  • AOmniWalkGravityVolume is effectively priority 0.
  • Any AOmniWalkTriggerZone with Priority > 0 overrides it.
  • When the winning zone is disabled via SetEnabled(false), the subsystem immediately promotes the next-highest zone for all affected actors.
  • The subsystem is accessible via GetGameInstance()->GetSubsystem<UOmniWalkZonePrioritySubsystem>() if you need to query it in C++.

Physics Field

UOmniWalkPhysicsField makes nearby physics-simulating objects fall in the same direction as the character's current gravity. Add it alongside UOmniWalkPro on the character. Each tick, it finds objects within FieldRadius and applies AddForce in the character's "down" direction.

Field Radius Visualized

Character out of range FieldRadius

Setup

Add UOmniWalkPhysicsField to the same character Blueprint (or C++ class) that has UOmniWalkPro. No configuration beyond FieldRadius is required for basic use. The component self-caches UOmniWalkPro at BeginPlay.

Properties

PropertyPurposeDefault
FieldRadiusSphere radius for object search (cm)500
GravityStrengthForce magnitude (cm/s²). Match to world gravity for realism.980
TickIntervalUpdate rate (seconds). Increase for better performance.0.05
MaxAffectedObjectsMax objects per update. Prevents spikes.20
AffectedTagsOnly affect actors with these tags. Empty = all physics actors.
ExcludedTagsNever affect actors with these tags. Takes precedence.
bDebugVisualizationDraw cyan sphere in PIE showing field radius.false

API

UOmniWalkPhysicsField* Field = FindComponentByClass<UOmniWalkPhysicsField>();

// Disable field temporarily (e.g. during zero-g sequence)
Field->SetFieldEnabled(false);

// Resize at runtime (e.g. power-up expands field)
Field->SetFieldRadius(1200.0f);

// Enumerate currently affected actors
TArray<AActor*> Affected = Field->GetAffectedActors();

// Listen for objects entering/leaving the field
Field->OnObjectEnterField.AddDynamic(this, &AMyClass::OnObjectEntered);
Field->OnObjectLeaveField.AddDynamic(this, &AMyClass::OnObjectLeft);

Surface Response

The Surface Response system maps Unreal Physical Materials to OmniWalk behavior modifiers. It has two parts: a data asset (UOmniWalkSurfaceResponseTable) that defines presets, and a component (UOmniWalkSurfaceResponse) that samples the surface underfoot each tick and applies the matching preset.

PhysicalMaterial on surface below
Table Lookup SurfaceResponseTable
Apply Multipliers Adhesion · Friction · Speed
OnSurfaceTypeChanged footstep routing

Step 1 — Create the Data Asset

  1. In the Content Browser: right-click → Miscellaneous → Data Asset.
  2. Choose OmniWalkSurfaceResponseTable as the class.
  3. Open the asset and add rows to the Entries array. Assign a Physical Material to each row.
  4. Leave Material as None on one entry to serve as the fallback (matched when no material is found).

Built-in Presets (C++ only)

Five named presets are available as static factory methods to populate entries programmatically:

PresetAdhesionFrictionSpeedAlignment
MakeIcePreset()×0.6×0.1×1.2×2.0
MakeMagneticPreset()×3.0×1.5×0.8×0.5
MakeRubberPreset()×1.2×3.0×0.9×1.0
MakeStickyPreset()×5.0×10.0×0.4×1.0
MakeZeroGPreset()×0.0×0.0×1.5×1.0

Step 2 — Add the Component

Add UOmniWalkSurfaceResponse alongside UOmniWalkPro on your character. Assign the data asset to ResponseTable. The component auto-binds to UOmniWalkPro's OnSurfaceAttached / OnSurfaceDetached events and resets multipliers automatically when off-surface.

// C++ constructor example
UOmniWalkSurfaceResponse* SR = CreateDefaultSubobject<UOmniWalkSurfaceResponse>(TEXT("SurfaceResponse"));
SR->ResponseTable = MyTableAsset;  // UOmniWalkSurfaceResponseTable*
SR->SampleInterval = 0.1f;        // Re-sample every 100 ms

FOmniWalkSurfaceEntry Fields

FieldEffectDefault
MaterialPhysical Material to match. None = fallback.None
AdhesionMultiplierScales UOmniWalkPro::AdhesionForce1.0
FrictionMultiplierScales CMC GroundFriction1.0
AlignmentSpeedMultiplierScales UOmniWalkPro::AlignmentSpeed1.0
WalkSpeedMultiplierScales CMC MaxWalkSpeed1.0
SurfaceTagFName broadcast via OnSurfaceTypeChanged. Use for footstep routing.None
FootstepSoundOptional sound asset. Retrieve from the tag callback.None

Footstep Routing

Bind OnSurfaceTypeChanged in Blueprint or C++ to drive footstep audio, VFX, or any per-surface logic:

// C++ bind
SurfaceResponse->OnSurfaceTypeChanged.AddDynamic(this, &AMyChar::OnSurfaceChanged);

void AMyChar::OnSurfaceChanged(FName SurfaceTag)
{
    if (SurfaceTag == "Ice")
    {
        // play ice footstep, spawn frost VFX
    }
    else if (SurfaceTag == NAME_None)
    {
        // off surface or unmatched material — reset to default
    }
}

UOmniWalkSurfaceResponse Properties

PropertyPurposeDefault
ResponseTableThe data asset to look up entries fromNone
SampleIntervalSeconds between re-samples. 0 = every tick.0.1
SampleChannelCollision channel for underfoot traceWorldStatic
SampleDistanceTrace half-length below actor origin (cm)200

Cinematic Control

UOmniWalkCinematic is designed for cutscenes and scripted sequences. It can freeze UOmniWalkPro's surface detection — preventing unexpected gravity changes during a camera animation — and smoothly interpolate gravity to any target direction over a configurable duration.

Cinematic Timeline

Cinematic Mode Active Surface Detection Suppressed Gravity Transition SetCinematicMode(true) SetGravityDir(...) TransitionComplete SetCinematicMode(false)

Typical Usage

UOmniWalkCinematic* Cin = FindComponentByClass<UOmniWalkCinematic>();

// --- Cutscene begins ---
Cin->SetCinematicMode(true);

// Smoothly flip gravity over 2 seconds (ease-in-out)
Cin->SetCinematicGravityDirection(FVector(0, 0, -1), 2.0f);

// Listen for completion
Cin->OnGravityTransitionComplete.AddDynamic(this, &AMyClass::OnFlipDone);

// --- Cutscene ends (call when sequence finishes) ---
Cin->SetCinematicMode(false);

One-Shot Helper

Set bAutoExitCinematicOnTransitionEnd = true to have the component automatically call SetCinematicMode(false) once the gravity transition completes. Useful for a simple "flip and resume" pattern without manually tracking the cutscene state.

// Auto-exit after flip completes — no manual SetCinematicMode(false) needed
Cin->bAutoExitCinematicOnTransitionEnd = true;
Cin->SetCinematicGravityDirection(FVector(0, 1, 0), 1.5f);

Properties & API Reference

MemberTypeNotes
SetCinematicMode(bool)MethodFreeze/unfreeze OmniWalkPro surface detection.
IsInCinematicMode()QueryReturns current cinematic state.
SetCinematicGravityDirection(TargetUp, Duration, bImmediate)MethodBegin smooth gravity transition. Duration 0 = instant snap.
SnapCinematicGravity(TargetUp)MethodInstant gravity snap. Convenience wrapper.
CancelGravityTransition()MethodStop in-progress transition; hold current direction.
GetTransitionProgress()Query (0..1)Returns 1.0 when idle or complete.
bAutoExitCinematicOnTransitionEndPropertyAuto-call SetCinematicMode(false) after transition.
bUseSmoothStepPropertytrue = ease-in-out (default), false = linear.
OnCinematicModeChangedDelegateBroadcast on every SetCinematicMode call.
OnGravityTransitionCompleteDelegateBroadcast when animation finishes or snaps.
Sequencer Integration: Bind SetCinematicMode and SetCinematicGravityDirection to Sequencer Event Track callbacks to drive gravity transitions directly from a Level Sequence timeline without any Blueprint boilerplate.

Patrol Path

AOmniWalkPatrolPath defines an ordered sequence of world-space waypoints using a USplineComponent. Each spline control point is a waypoint. Place this actor in the level, edit the spline, and assign it to UOmniWalkAIPatrol on your AI pawn.

Loop

After the last point, wrap back to the first. Spline is rendered as a closed loop. Best for patrol circuits.

Ping-Pong

After the last point, the AI reverses direction back to the first. Useful for guards patrolling a hallway.

Once

Stop at the last waypoint and fire OnPatrolPathComplete. Use for escort or one-time scripted movement.

Properties

PropertyPurposeDefault
LoopModeLoop / PingPong / OnceLoop
WaypointHeightOffsetOffset waypoints along the spline up-vector (cm). Use to lift points above curved geometry.0
bDebugVisualizationDraw path and waypoint spheres during PIEtrue
DebugPathColorColor of debug lines and spheresCyan

Query API

// Number of control points / waypoints
int32 N = PatrolPath->GetPatrolPointCount();

// World location of waypoint i (applies WaypointHeightOffset)
FVector Loc = PatrolPath->GetPatrolPointLocation(i);

// World transform (includes spline orientation at that point)
FTransform T = PatrolPath->GetPatrolPointTransform(i);

// Next index given current index and direction (+1 / -1)
// bReversed is set true when PingPong mode flips the direction
bool bReversed;
int32 Next = PatrolPath->GetNextPointIndex(Current, 1, bReversed);
// Returns -1 in Once mode when the end is reached

// Find the waypoint closest to an actor's position
int32 Nearest = PatrolPath->GetNearestPointIndex(MyPawn->GetActorLocation());

AI Patrol

UOmniWalkAIPatrol drives an AI pawn along an AOmniWalkPatrolPath using the pawn's AAIController. It issues MoveToLocation requests for each waypoint in sequence, waits for the controller's path-following result, optionally idles at each stop via WaypointWaitTime, then advances to the next point.

Patrol Loop

StartPatrol MoveToLocation In Transit PathFollowing Arrived OnReachedPatrolPoint Wait WaypointWaitTime

Setup

  1. Place an AOmniWalkPatrolPath actor and shape the spline. Set the LoopMode.
  2. On your AI character Blueprint, add UOmniWalkAIPatrol as a component.
  3. Set PatrolPath to point at the path actor.
  4. Ensure the character has an AAIController and a Nav Mesh Bounds Volume covers the patrol area.
  5. Enable bAutoStartOnBeginPlay (default) or call StartPatrol() manually.
Nav Mesh on Arbitrary Surfaces

The standard UE Nav Mesh is world-axis-aligned. For AI patrolling on walls or ceilings, place a Nav Mesh Bounds Volume that encompasses the patrol area and enable Project Down on it, or use the Recast Nav Mesh's AgentMaxStepHeight to allow traversal of steep geometry. For fully off-axis surfaces (e.g. a vertical wall), consider calling AddMovementInput directly from a custom AI task instead of navmesh pathing.

Properties

PropertyPurposeDefault
PatrolPathThe AOmniWalkPatrolPath actor to followNone
bOverrideLoopModeWhen true, LoopModeOverride takes precedence over the path's own modefalse
LoopModeOverrideOverride value (active when bOverrideLoopMode = true)Loop
AcceptanceRadiusDistance to consider a waypoint "reached" (cm)50
StartWaypointIndexFirst waypoint index. -1 = nearest to actor position.0
WaypointWaitTimeIdle seconds at each waypoint before advancing0.5
bAutoStartOnBeginPlayAutomatically begin patrol one frame after BeginPlaytrue

Control API

UOmniWalkAIPatrol* Patrol = FindComponentByClass<UOmniWalkAIPatrol>();

// Start / resume patrol
Patrol->StartPatrol();

// Pause at current position (in-flight move finishes naturally)
Patrol->PausePatrol();
Patrol->ResumePatrol();

// Full stop (aborts in-flight move)
Patrol->StopPatrol();

// Hot-swap path at runtime
Patrol->SetPatrolPath(NewPathActor);

// Teleport logic: jump to a specific waypoint index
Patrol->JumpToWaypoint(3);

// State queries
bool bActive  = Patrol->IsPatrolling();
int32 Current = Patrol->GetCurrentWaypointIndex();

Events

// Fires each time a waypoint is reached
Patrol->OnReachedPatrolPoint.AddDynamic(this, &AMyClass::OnWaypointReached);

// Fires when a Once-mode path ends at the last point
Patrol->OnPatrolPathComplete.AddDynamic(this, &AMyClass::OnPatrolDone);

void AMyClass::OnWaypointReached(int32 PointIndex)
{
    // e.g. play an animation, trigger dialogue, update AI state
    UE_LOG(LogTemp, Log, TEXT("AI reached waypoint %d"), PointIndex);
}

Support & Legal

Troubleshooting Modules

Gravity Zones Not Applying

Symptom: Character enters a Trigger Zone or Spline Volume but gravity doesn't change.

  • Check Priority: It must be higher than the base AOmniWalkGravityVolume (Priority 0). Overlapping zones require explicit priority sorting.
  • Check Targeting: If using TagBased or SpecificActors TargetMode, ensure the character meets the criteria.
  • Verify Collision: The actor must generate overlap events with the zone's collision shape.

Physics Field Not Affecting Objects

Symptom: Nearby crates or debris ignore the character's gravity.

  • Ensure the objects have Simulate Physics enabled.
  • Check Tags: If AffectedTags is not empty, the object must have one of those tags. Ensure it's not in ExcludedTags.
  • Enable bDebugVisualization on the Physics Field to visually confirm the objects are inside the FieldRadius.

Surface Response Failing

Symptom: Footstep sounds or adhesion multipliers are not updating when walking on new surfaces.

  • Verify the floor mesh has a valid Physical Material assigned in its collision settings.
  • Ensure the SampleChannel (default WorldStatic) correctly traces against your floor geometry.
  • Check that your ResponseTable data asset includes a row with Material set to None as a fallback.

AI Patrol Not Moving

Symptom: The AI pawn stays at its spawn location instead of following the patrol path.

  • Ensure the pawn is possessed by an AAIController.
  • Verify a Nav Mesh Bounds Volume covers the path. Press 'P' in the viewport to visualize the nav mesh.
  • For steep or off-axis surfaces, check that the Nav Mesh projects correctly or use AgentMaxStepHeight.
  • Confirm PatrolPath is set in the UOmniWalkAIPatrol component.

Cinematic Transitions Interrupting

Symptom: The character detaches or jerks around during a scripted gravity sequence.

  • Always call SetCinematicMode(true) before initiating the transition to suppress OmniWalk's standard surface detection logic.

About

Budapest, HU

GregOrigin

Created by Andras Gregori @ Gregorigin, a single dad currently based outside Budapest, HU.

"Building tools that empower creators to shape worlds."