Chaos Mover
Physics-threaded character movement simulation with networked resimulation and thread-safe simulation authoring.
Chaos Mover is an experimental feature. For in-depth discussion, community feedback, and known limitations, refer to the Unreal Engine Developer Community forum post.
Overview
Chaos Mover is an extension of the Mover plugin designed for character movement simulation running on the Physics Thread at a fixed timestep. It enables physically based character movement, improved simulation of characters interacting with networked physics objects, and more accurate physical interactions between players over the network.
Chaos Mover shares the same core Mover API and follows the same general authoring model as standard Mover, but its execution model, networking architecture, and threading requirements differ significantly. Understanding these differences is essential before using Chaos Mover in your project.
Movement modes are defined using the same FMoverTickStartData, FProposedMove, and data container patterns as standard Mover — the shared API is a familiar authoring contract. It is not a compatibility guarantee: most existing Mover movement mode implementations are not thread-safe and cannot be used with Chaos Mover without significant rework. Any implementation that touches Game Thread state, UObjects, or engine systems outside of marshalled data will need to be rewritten with Physics Thread safety in mind.
Requirements
Physics Async Mode
Chaos Mover requires the physics simulation to run asynchronous to the Game Thread (GT). This is a hard requirement: the fixed-timestep simulation loop runs on the Physics Thread (PT), not on the Game Thread, which is a fundamental departure from how standard Mover operates.
Because the simulation runs on the Physics Thread, any data it accesses must be explicitly marshalled from the Game Thread. Direct access to Game Thread state from within simulation logic is not safe and is not supported. See DATA MARSHALLING for the mechanisms Chaos Mover provides for this.
Concretely, the following rules apply to all simulation logic:
-
Do not access
UObjectproperties or callUObjectmethods unless those objects have been designed for Physics Thread access. -
Do not read or write Game Thread state directly from movement mode logic.
-
Do not use engine subsystems, the world context, or gameplay tag infrastructure in ways that touch Game Thread data.
Writing thread-safe movement logic also has benefits beyond Chaos Mover. Games with high performance requirements often need to run game logic in parallel with movement and physics processing. Movement code authored with Physics Thread safety in mind is well-positioned to participate in those parallel execution models.
To enable async physics, set the following in your project:
[/Script/Engine.PhysicsSettings]
AsyncFixedTimeStepSize=0.016667 ; adjust to your target fixed step
bTickPhysicsAsync=true
Execution Flow
This section gives a brief end-to-end picture of how a Chaos Mover simulation frame progresses.
-
The Game Thread advances time. Once enough time has elapsed to warrant one or more fixed simulation steps, the Game Thread prepares input data for each step and marshals it to the Physics Thread using the physics thread marshalling system.
-
The Physics Thread executes the simulation at the fixed timestep. For each step, it processes the marshalled input, runs the movement mode state machine, and produces output describing the resulting character state. This simulation logic mirrors what the standard Mover state machine does on the Game Thread; a separate implementation was necessary to meet the thread safety requirements of running on the Physics Thread. The driver here is ChaosMoverBackend, which calls
UChaosMoverSimulation::SimulationTick— notUMoverComponent::SimulationTick. Code that hooks into or overrides the latter directly, outside of a movement mode, will not fire in Chaos Mover. -
In a networked game, the Network Physics Component may trigger a rollback and resimulation in response to a server correction. The world is rolled back to the frame requiring correction, the client state is replaced with the authoritative server state, and the physics thread advances forward again to the current frame by replaying the inputs stored in the Network Physics Component’s input record. Any subsequent authoritative states received from the server are also applied during this replay. See NETWORKING.
-
The output from each simulation step is marshalled back to the Game Thread. Every Game Thread frame, the accumulated simulation outputs are used to produce an interpolated result at a fixed time offset behind the current Game Thread time. This deliberate look-back ensures that physics output for that point in time has always been computed and marshalled back before the interpolation runs. When the Game Thread runs faster than the physics step rate, multiple frames will interpolate between the same pair of consecutive physics outputs at slightly advancing positions.
Built-In Movement Modes And Layered Moves
Movement Modes
Chaos Mover ships the following movement modes. All character modes require a character physics constraint to be configured on the actor.
UChaosWalkingMode
Ground-based walking. Uses the character ground constraint to handle floor interaction, step-up, and slope limiting.
UChaosFallingMode
Airborne movement. Controls air control fraction, terminal velocity, and lateral friction while the character is off the ground.
UChaosSwimmingMode
Water movement with depth-based speed scaling, buoyancy, and bobbing physics.
UChaosFlyingMode
Free-flying movement with no ground constraint.
Two additional walking modes provide spring-based smoothing for acceleration, deceleration, and facing transitions. They mirror the smoothing model from Mover’s USmoothWalkingMode:
UChaosSimpleWalkingMode
Abstract base that exposes a GenerateWalkMove hook. Derive from this to shape or smooth ground motion with custom logic.
UChaosSmoothWalkingMode
Concrete spring-smoothed walking mode. Use this when you want Mover-style smooth locomotion with no additional customisation.
For non-player actors such as moving platforms, Chaos Mover also provides:
UChaosPathedMovementMode
Movement along a predefined path. Supports point-to-point, spline, and elliptical path patterns.
Layered Moves
The following layered moves from the base Mover plugin support async execution and are compatible with Chaos Mover:
FLayeredMove_LinearVelocity
Applies a continuous velocity contribution for its duration. Supports an optional magnitude curve to shape the velocity over time.
FLayeredMove_Launch
Applies a one-shot launch velocity. Optionally forces the character into a specific movement mode on launch.
FLayeredMove_AnimRootMotion_Async
Drives character displacement from a montage on the simulation thread. Unlike the game-thread root motion variant, this move owns animation progression: the simulation thread is the authority on how far through the animation the character has advanced, rather than the animation system advancing independently on the Game Thread. Blend-out and finish are detected from position thresholds and duration expiry, not by polling the animation instance. This enables tight coupling between physical movement and animation at the cost of not supporting branching or looping animations. See EXAMPLES for usage.
Instant Movement Effects
Chaos Mover provides one character-specific instant movement effect:
FChaosCharacterApplyVelocityEffect
Applies a velocity or impulse for a single simulation tick. Supports additive velocity, absolute velocity, and impulse application modes.
The following instant effects from the base Mover plugin are also async-safe and can be used with Chaos Mover:
FJumpImpulseEffect
A single upward velocity impulse.
FTeleportEffect
Teleports the actor to a new location/rotation.
Networking
Chaos Mover’s networking model is built on the Network Physics Component rather than the standard Mover networking infrastructure. Chaos Mover’s networking capabilities and limitations are therefore directly coupled to the development state of the Network Physics plugin.
Replication Mode
Chaos Mover uses the Resimulation replication mode provided by Network Physics. Each client runs a predictive local simulation, maintaining a rolling history of inputs and states. When the server sends an authoritative state correction, the client rolls back to the corrected frame, applies the server’s state, and resimulates forward by replaying its buffered inputs to arrive at a corrected present state. When this happens, the entire physics world resimulates — not just the corrected character. This is an intentional design tradeoff: because Chaos Mover’s primary goal is correct physical interactions in a rich networked world (characters pushing physics objects, reacting to explosions, interacting with other simulated bodies), a partial correction applied to one actor in isolation would produce inconsistent results with the rest of the world. A full world resim is the price of that correctness.
The cost of full world resimulations is significant, particularly in scenes with many physics actors. Profile resimulation frequency in your target scenarios and tune correction thresholds via UNetworkPhysicsSettingsDataAsset.
An important consequence of this model is that a given simulation frame may execute more than once — once predictively as the client advances, and again during a correction. Movement modes must be authored with this in mind: simulation logic must be deterministic given the same inputs and starting state, and side effects such as spawning objects or triggering audio must be guarded against running during resimulation.
Game Thread Events and Resimulation
Rollback and resimulation cause simulation events to fire on the Game Thread for situations that have already been processed, and the order in which they fire may not reflect the final authoritative outcome.
Mode change events illustrate this clearly. Consider a character that jumps, transitioning from walking to falling. A server correction that rolls the character back to before the jump fires a mode change back to walking, followed — if the resimulation confirms the jump — by another mode change to falling. A Game Thread listener tracking landings and jumps by watching mode changes would incorrectly conclude the character landed and jumped again.
If the server determines the jump was not valid (say, the ability was disabled by a gameplay system at that frame), the mode change to falling will not occur after the rollback. The listener would conclude the character just landed, when it never left the ground.
Events carry flags indicating whether they were produced during a rollback or a resimulation, which can be used to filter them. In cases where those flags are not sufficient, a more reliable pattern is available: all events produced by a single physics output are delivered together in one batch. Game Thread code can cache the pre-output state, accumulate all changes from the batch, and diff against the cached state to determine the net result. Only the net change needs to be acted on.
An example of this pattern is implemented in UChaosCharacterMoverComponent::DispatchSimulationEvents for the character’s crouch state.
Client-Server Timing
The server deliberately runs behind clients by a controlled network offset. Clients continuously adjust their simulation rate so that the server always receives their inputs before it needs to simulate the corresponding frame. This gives network messages time to arrive from all clients, allowing the server to simulate each frame with a complete picture of what every player is doing.
The server simulates each frame exactly once and is always authoritative. It never rolls back or resimulates.
Proxy Roles
Autonomous Proxy
The client that locally controls the character. It runs ahead of the server by the network offset, sends its inputs to the server, and receives authoritative state corrections back.
Sim Proxy
The representation of a remotely controlled character on a client that does not locally control it. The server relays both the authoritative states and the inputs of the controlling autonomous proxy to sim proxies. Because the autonomous proxy runs ahead of the server, and the server relays inputs with some lag, sim proxies frequently receive inputs from their own past that contradict what they used in their first-pass simulation. As a result, sim proxies continuously trigger full world resimulations whenever the controlling player is actively providing input.
Setup
For resimulation to work correctly, the Physics Replication Mode on the character’s physics actor must be set to Resimulation. This is required for any actor using Chaos Mover.
Additional network simulation parameters — such as input buffer size, history depth, and correction thresholds — can be tuned by adding a UNetworkPhysicsSettingsComponent to the actor and pointing it to a UNetworkPhysicsSettingsDataAsset configured for your project’s needs.
Queuing Moves And Instant Movement Effects
Queuing from the Game Thread vs. the Simulation
The golden path for Chaos Mover is to implement all movement logic on the physics thread, driven purely by input. When instant movement effects (IMEs), layered moves, and layered move instances are queued from within simulation logic, no networking is required — each endpoint produces them independently as a natural consequence of running the same simulation logic, which is expected to be deterministic given the same inputs.
They can also be queued from the Game Thread via the Mover Component’s queuing functions, in which case they are networked.
This pattern will feel familiar to anyone coming from standard Mover or the Character Movement Component, where all movement decisions are made on the Game Thread. Chaos Mover deliberately supports and networks Game Thread queuing for several reasons: it is a natural model for authors with that background and for technical designers prototyping in Blueprint; the networking provides a mechanism to apply effects on or near the correct simulation frame rather than leaving them entirely uncoordinated across endpoints; and it avoids requiring all gameplay decision logic to run on the physics thread, along with the overhead of marshalling the necessary gameplay context there.
Despite those advantages, Game Thread queuing carries two significant drawbacks compared to expressing the same effect as simulation logic:
Frame correctness and resimulation. The physics simulation runs at a fixedstep on all machines; the Game Thread runs at a variable frame rate thatdiffers across them. Game Thread logic therefore cannot reliably identifythe same simulation step as other endpoints, making GT-queued effectsinherently imprecise about which frame they apply on. They also do notparticipate in resimulation: if conditions have changed by the time arollback and resim executes
because the server corrected the character’s
velocity, or a physics interaction unfolded differently
whatever was
originally queued is what the resim receives, regardless of whether itremains the correct response.
Increased cheat surface. Raw input is minimal and constrained
a direction,
a button state, a magnitude. IMEs and moves carry full effect payloads:velocity vectors, durations, launch parameters. Embedding those payloads insomething a client can author gives a cheating client a much larger surfaceto exploit than raw input alone.
Game Thread queuing is a practical path for prototyping and for games where these tradeoffs are acceptable. Movement that must meet a competitive quality bar may eventually need to be converted to Physics Thread logic driven purely by input. When Game Thread queuing is the right choice — for example, a one-shot effect whose payload cannot be recomputed from input alone — the two networking modes below describe how to do it correctly.
Networking Queued Moves and Effects
IMEs, layered moves, and layered move instances can be networked in one of two ways. Which mode is active is controlled by two console variables:
- ChaosMover.Networking.NetworkInstantMovementEffectsWithSimActions
- ChaosMover.Networking.NetworkMovesWithSimActions
These can be set per-project. At runtime, UChaosMoverBlueprintLibrary exposes IsNetworkingInstantMovementEffectsWithSimActions() and IsNetworkingMovesWithSimActions() to query which mode is active, so Blueprint logic can adapt accordingly.
Input Mode (CVars = false)
In input mode, IMEs and moves are embedded in the networked input cmd. The typical authoring pattern is:
-
In PreSim (before the simulation step), detect the trigger condition by reading the current simulation input.
-
Call QueueInstantMovementEffect / QueueLayeredMove / QueueLayeredMoveInstance on the simulation. The backend packs these into the input cmd for that step.
-
The packed input is sent through the Network Physics input pipeline and replayed during resimulation like any other input data.
This mode is client-authoritative: the client’s detection logic decides when an effect fires, and the server accepts it because it arrives in the replicated input history.
Tradeoffs:
- Straightforward to author; detection logic runs in PreSim with immediate access to the triggering input.
- No per-effect server verification overhead; the server just replays the input.
- Client-authoritative: a cheating client could inject effects the server would not independently fire.
- Effects that depend on floating-point simulation state may diverge slightly between client and server, requiring careful resim tolerance tuning.
Sim Actions Mode (CVars = true)
In sim actions mode, IMEs and moves are networked via the Network Physics sim action system using the “Proposed” author style. Each endpoint — client, server, and sim proxy — independently detects the same trigger condition and enqueues the same action. The server acts as the authority: if the server’s independently produced action matches the client’s within tolerance, no correction is needed; if they differ, a correction is issued.
The typical authoring pattern is:
-
In PostSim (after the simulation step), detect the trigger condition by reading GetLastInputCmd() — the input that was actually used for the step that just completed.
-
Call QueueInstantMovementEffect / QueueLayeredMove / QueueLayeredMoveInstance on the simulation. The backend routes these as sim actions rather than embedding them in the input cmd.
Detection must happen in PostSim, not PreSim. The server cannot read generated input during PreSim — it only becomes available in PostSim via GetLastInputCmd() after the step completes. Using PreSim input in sim actions mode will cause the server to miss the trigger, resulting in persistent corrections.
This introduces one frame of lag relative to the input mode path for all endpoints: detection is shifted from PreSim to PostSim, so the effect fires in the step after the one that contained the triggering input rather than in the same step.
Tradeoffs:
- Server-authoritative and cheat-resistant: the server independently verifies the trigger and can reject actions the client should not have fired.
- Appropriate for competitive games where client-authoritative effects are unacceptable.
- Slightly more complex authoring: detection must be moved to PostSim.
- One additional frame of lag for all endpoints (PreSim vs PostSim detection shift).
- Both client and server must independently reproduce the same detection logic.
Expanding Tolerance for Proposed Actions
Because client and server run detection independently, floating-point differences in simulation state (e.g. a velocity that is 0.01 cm/s different) can cause them to produce slightly different action payloads, triggering unnecessary corrections.
To widen the acceptance window, override IsNearlyEqualTo on your struct:
FInstantMovementEffectsubclasses: override IsNearlyEqualTo(constFInstantMovementEffect&)FLayeredMoveBasesubclasses: override IsNearlyEqualTo(constFLayeredMoveBase&)FLayeredMoveInstancedDatasubclasses: override IsNearlyEqualTo(constFLayeredMoveInstancedData&)
The default implementation uses UScriptStruct::CompareScriptStruct, which performs strict field-by-field equality (or operator== if TStructOpsTypeTraits declares WithIdenticalViaEquality). Override this to accept values within an epsilon, compare only the fields that matter for the action, or apply any other fuzzy matching appropriate for the effect.
The Other argument is guaranteed to be the same struct subtype as the receiver.
Authority Sim Actions
The Authority functions always network via sim actions, regardless of the CVar settings above. They are server-only (they no-op silently on clients) and are intended for effects and moves initiated by the server rather than detected independently by all roles:
UChaosMoverBlueprintLibrary::QueueLayeredMove_AuthorityUChaosMoverBlueprintLibrary::QueueLayeredMoveInstance_AuthorityUChaosMoverBlueprintLibrary::QueueInstantMovementEffect_AuthorityUChaosMoverBlueprintLibrary::ScheduleLayeredMove_AuthorityUChaosMoverBlueprintLibrary::ScheduleLayeredMoveInstance_AuthorityUChaosMoverBlueprintLibrary::ScheduleInstantMovementEffect_Authority
The Queue variants apply the action as soon as possible. Clients that have already simulated past the target frame will receive a correction.
The Schedule variants add a delay (sourced from UNetworkPhysicsSettingsComponent::EventSchedulingMinDelaySeconds) large enough for all endpoints to apply the action on the same physics frame without triggering a correction. Use the Schedule variants when frame synchronization matters, such as a forced launch or teleport that must not produce a visible correction on the client.
Use Authority functions for:
- Server-initiated knockbacks or forced launches
- Scripted teleports triggered by server-side gameplay events
- Any
IMEor move the server decides to apply regardless of client state
Authority functions always use sim actions regardless of whether bNetworkMovesWithSimActions or bNetworkInstantMovementEffectsWithSimActions is set. They bypass the input mode entirely.
Data Marshalling
Chaos Mover provides three mechanisms for marshalling data from the Game Thread to the Physics Thread. All three use the same FMoverDataCollection data structure from Mover: a typed container of FMoverDataStructBase-derived structs. This shared foundation makes it straightforward to move data between mechanisms as requirements evolve, and makes all marshalled data compatible with the Chaos Visual Debugger for recording and display, provided properties are marked UPROPERTY(VisibleAnywhere).
Networked Input
Input intended for use in the simulation is packaged as networked input and marshalled through the Network Physics Component’s input pipeline. This input is included in the history used for prediction and resimulation, so it is available consistently whether the simulation is running predictively, resimulating, or replaying from a snapshot.
Beyond raw player controls, the networked input also carries the suggested movement mode, queued IMEs, layered moves, and layered move instances — see QUEUING MOVES AND INSTANT MOVEMENT EFFECTS for how these are authored and networked.
Define your input struct as a FNetworkPhysicsData-derived type and register it with the Network Physics Component. The Chaos Mover backend will make it available to your movement modes at the correct simulation step.
Networked State
Networked state represents the authoritative state of the character simulation that is replicated and used for reconciliation. Like networked input, it is managed by the Network Physics Component and participates in rollback and resimulation.
Use networked state for data that must be consistent across clients and server, such as character velocity, position corrections, or any persistent simulation variable.
Local Sim Input
Local sim input is a mechanism for passing non-networked, one-shot data from the Game Thread to the Physics Thread for a single simulation step. It is suitable for data that is locally generated and does not need to be reconciled across the network — for example, local environmental queries or transient gameplay triggers.
Local sim input is not included in the prediction/resimulation history. Do not use it for data that must be consistent across prediction and reconciliation.
If a struct used as local sim input later needs to be reconciled across the network, moving it to networked state is straightforward: because it already derives from FMoverDataStructBase, it is already compatible with the networked state data collection.
Debugging
Mover Data CVD Plugin
Chaos Mover supports debugging via the Mover Data CVD plugin, which integrates with the Chaos Visual Debugger (CVD) to trace simulation data at each physics step.
To enable it, ensure the MoverDataCVD plugin is enabled in your project and that CVD recording is active. To capture Mover-specific data, enable the following CVD channels before recording:
Channel names — placeholder, to be filled in.
Mover data appears as extra particle data in the CVD timeline.
Adding Custom Traced Data
You can extend the CVD traces with your own simulation data to aid debugging. To add custom traced data to the CVD output from within a movement mode or modifier:
-
Implement
ICVDDebugObjectInterfaceon your data struct, or use the existing trace helpers provided in MoverDataCVD. -
Call the appropriate trace macro or helper function at the point in your simulation logic where the data is produced.
-
Verify the data appears in
CVDby recording a session and inspecting the relevant physics step.
Refer to the existing Chaos Mover movement mode implementations for examples of how custom data is wired into the trace pipeline.
Examples
MoverExamples Plugin
The MoverExamples plugin contains a simple Chaos Mover pawn intended as a starting point for new projects. It implements a small set of movement modes — walking, falling, and swimming — and supports crouching, jumping, dashing, and vaulting. The goal is to demonstrate the basic authoring patterns without the complexity of a production character.
Many of the movement modes available in the standard Mover plugin are not async-friendly and were not adapted for use with Chaos Mover. The example set was deliberately kept minimal for this reason.
One notable move included is a root motion extraction move with static warping, used to drive the vaulting action. See FLayeredMove_AnimRootMotion_Async in BUILT-IN MOVEMENT MODES AND LAYERED MOVES.
Anim Sandbox
A second example pawn is available in the anim sandbox. It demonstrates higher-quality character animation using motion matching with trajectory prediction, driven by Chaos Mover. This pawn is the better reference for authors targeting animation quality closer to a shippable bar.
See Also
- Mover Overview
- Network Physics Component
- Chaos Visual Debugger