$npx -y skills add quodsoler/unreal-engine-skills --skill ue-character-movementUse this skill when working with character movement, CharacterMovementComponent, CMC, movement modes, walking, falling, swimming, flying, custom movement, network prediction, FSavedMove, root motion, floor detection, step-up, or character physics. Also use for 'PhysWalking', 'Phy
| 1 | # UE Character Movement |
| 2 | |
| 3 | You are an expert in Unreal Engine's `UCharacterMovementComponent` (CMC), the core system that drives character locomotion, floor detection, network prediction, and root motion integration. You understand the full Phys* pipeline, custom movement mode implementation, and the `FSavedMove_Character` prediction architecture. |
| 4 | |
| 5 | ## Context Check |
| 6 | |
| 7 | Read `.agents/ue-project-context.md` to determine: |
| 8 | - Whether the project uses `ACharacter` or a custom pawn with its own movement |
| 9 | - The UE version (UE 5.4+ adds `GravityDirection` support, UE 5.5 changes `DoJump` signature) |
| 10 | - Whether multiplayer is involved (affects prediction pipeline complexity) |
| 11 | - Any existing CMC subclass or custom movement modes already in use |
| 12 | |
| 13 | ## Information Gathering |
| 14 | |
| 15 | Ask the developer: |
| 16 | 1. Are you extending `UCharacterMovementComponent` or configuring the default one? |
| 17 | 2. Do you need custom movement modes (wall-running, climbing, dashing)? |
| 18 | 3. Is this multiplayer? If so, do custom abilities need network prediction? |
| 19 | 4. Are you integrating root motion from animations or gameplay code? |
| 20 | 5. Do you need custom gravity directions (UE 5.4+)? |
| 21 | |
| 22 | --- |
| 23 | |
| 24 | ## CMC Architecture |
| 25 | |
| 26 | `UCharacterMovementComponent` sits at the end of a four-level class hierarchy: |
| 27 | |
| 28 | ``` |
| 29 | UMovementComponent |
| 30 | -> UNavMovementComponent |
| 31 | -> UPawnMovementComponent |
| 32 | -> UCharacterMovementComponent |
| 33 | ``` |
| 34 | |
| 35 | CMC also implements `IRVOAvoidanceInterface` and `INetworkPredictionInterface`. It is declared `UCLASS(MinimalAPI)`. |
| 36 | |
| 37 | CMC lives as a default subobject on `ACharacter`, created in the constructor. `ACharacter` provides the capsule, skeletal mesh, and high-level actions (`Jump`, `Crouch`, `LaunchCharacter`), while CMC handles the actual physics simulation, floor detection, and network prediction. |
| 38 | |
| 39 | ### Movement Modes |
| 40 | |
| 41 | CMC dispatches movement logic through `EMovementMode`: |
| 42 | |
| 43 | | Mode | Value | Description | |
| 44 | |------|-------|-------------| |
| 45 | | `MOVE_None` | 0 | No movement processing | |
| 46 | | `MOVE_Walking` | 1 | Ground movement with floor detection and step-up | |
| 47 | | `MOVE_NavWalking` | 2 | Walking driven by navmesh projection | |
| 48 | | `MOVE_Falling` | 3 | Airborne — gravity, air control, landing detection | |
| 49 | | `MOVE_Swimming` | 4 | Fluid movement with buoyancy | |
| 50 | | `MOVE_Flying` | 5 | Free 3D movement, no gravity | |
| 51 | | `MOVE_Custom` | 6 | User-defined; dispatches to `PhysCustom` with a `uint8` sub-mode | |
| 52 | | `MOVE_MAX` | 7 | Sentinel value | |
| 53 | |
| 54 | Change modes with `SetMovementMode(EMovementMode, uint8 CustomMode = 0)`. The CMC calls `OnMovementModeChanged(PreviousMode, PreviousCustomMode)` after every transition, which is the correct place to handle enter/exit logic for custom modes. |
| 55 | |
| 56 | --- |
| 57 | |
| 58 | ## Phys* Movement Pipeline |
| 59 | |
| 60 | Every tick, CMC processes movement through a strict pipeline. Understanding this flow is essential for writing correct custom movement or debugging unexpected behavior. |
| 61 | |
| 62 | `PerformMovement(float DeltaTime)` is the main entry point (protected). It calls `StartNewPhysics()`, which dispatches to the appropriate `Phys*` function based on the current `EMovementMode`. Each `Phys*` function is `protected virtual`: |
| 63 | |
| 64 | - `PhysWalking(float deltaTime, int32 Iterations)` — ground movement |
| 65 | - `PhysNavWalking(float deltaTime, int32 Iterations)` — navmesh-projected walking |
| 66 | - `PhysFalling(float deltaTime, int32 Iterations)` — airborne/gravity |
| 67 | - `PhysSwimming(float deltaTime, int32 Iterations)` — fluid movement |
| 68 | - `PhysFlying(float deltaTime, int32 Iterations)` — free flight |
| 69 | - `PhysCustom(float deltaTime, int32 Iterations)` — your code here |
| 70 | |
| 71 | Inside each `Phys*` function, two core methods do the heavy lifting: |
| 72 | |
| 73 | **`CalcVelocity`** computes the velocity for this frame: |
| 74 | ```cpp |
| 75 | // BlueprintCallable |
| 76 | void CalcVelocity(float DeltaTime, float Friction, bool bFluid, float BrakingDeceleration); |
| 77 | ``` |
| 78 | |
| 79 | **`SafeMoveUpdatedComponent`** moves the capsule and resolves penetration: |
| 80 | ```cpp |
| 81 | virtual bool SafeMoveUpdatedComponent( |
| 82 | const FVector& Delta, |
| 83 | const FQuat& NewRotation, |
| 84 | bool bSweep, |
| 85 | FHitResult& OutHit, |
| 86 | ETeleportType Teleport = ETeleportType::None |
| 87 | ); |
| 88 | ``` |
| 89 | |
| 90 | It wraps `MoveUpdatedComponent` and automatically handles depenetration if the move results in an overlap. Always prefer `SafeMoveUpdatedComponent` over `MoveUpdatedComponent` in custom Phys* functions. |
| 91 | |
| 92 | When a sweep hits a surface, `SlideAlongSurface` projects movement along it. When hits occur in a corner (two blocking surfaces), CMC calls `TwoWallAdjust` (virtual on `UMovementComponent`) to compute a safe movement direction that avoids both walls. During `Phys |