ue-character-movement

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UE Character Movement

UE 角色移动

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.
你是Unreal Engine中
UCharacterMovementComponent
(CMC)的专家,CMC是驱动角色移动、地面检测、网络预测和根运动集成的核心系统。你熟悉完整的Phys*管线、自定义移动模式实现以及
FSavedMove_Character
预测架构。

Context Check

上下文检查

Read
.agents/ue-project-context.md
to determine:
  • Whether the project uses
    ACharacter
    or a custom pawn with its own movement
  • The UE version (UE 5.4+ adds
    GravityDirection
    support, UE 5.5 changes
    DoJump
    signature)
  • Whether multiplayer is involved (affects prediction pipeline complexity)
  • Any existing CMC subclass or custom movement modes already in use
阅读
.agents/ue-project-context.md
以确定:
  • 项目是否使用
    ACharacter
    或带有自定义移动逻辑的自定义Pawn
  • UE版本(UE 5.4+新增
    GravityDirection
    支持,UE 5.5修改了
    DoJump
    的签名)
  • 是否涉及多人游戏(会影响预测管线的复杂度)
  • 是否已存在CMC子类或自定义移动模式

Information Gathering

信息收集

Ask the developer:
  1. Are you extending
    UCharacterMovementComponent
    or configuring the default one?
  2. Do you need custom movement modes (wall-running, climbing, dashing)?
  3. Is this multiplayer? If so, do custom abilities need network prediction?
  4. Are you integrating root motion from animations or gameplay code?
  5. Do you need custom gravity directions (UE 5.4+)?

询问开发者:
  1. 你是要扩展
    UCharacterMovementComponent
    还是配置默认的组件?
  2. 是否需要自定义移动模式(跑墙、攀爬、冲刺)?
  3. 这是多人游戏项目吗?如果是,自定义能力是否需要网络预测?
  4. 你是否要从动画或游戏玩法代码中集成根运动?
  5. 是否需要自定义重力方向(UE 5.4+)?

CMC Architecture

CMC架构

UCharacterMovementComponent
sits at the end of a four-level class hierarchy:
UMovementComponent
  -> UNavMovementComponent
    -> UPawnMovementComponent
      -> UCharacterMovementComponent
CMC also implements
IRVOAvoidanceInterface
and
INetworkPredictionInterface
. It is declared
UCLASS(MinimalAPI)
.
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.
UCharacterMovementComponent
位于四层类继承结构的最底层:
UMovementComponent
  -> UNavMovementComponent
    -> UPawnMovementComponent
      -> UCharacterMovementComponent
CMC还实现了
IRVOAvoidanceInterface
INetworkPredictionInterface
,它被声明为
UCLASS(MinimalAPI)
CMC作为默认子对象存在于
ACharacter
中,在构造函数中创建。
ACharacter
提供碰撞胶囊、骨骼网格体和高层动作(
Jump
Crouch
LaunchCharacter
),而CMC负责实际的物理模拟、地面检测和网络预测。

Movement Modes

移动模式

CMC dispatches movement logic through
EMovementMode
:
ModeValueDescription
MOVE_None
0No movement processing
MOVE_Walking
1Ground movement with floor detection and step-up
MOVE_NavWalking
2Walking driven by navmesh projection
MOVE_Falling
3Airborne — gravity, air control, landing detection
MOVE_Swimming
4Fluid movement with buoyancy
MOVE_Flying
5Free 3D movement, no gravity
MOVE_Custom
6User-defined; dispatches to
PhysCustom
with a
uint8
sub-mode
MOVE_MAX
7Sentinel value
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.

CMC通过
EMovementMode
分发移动逻辑:
模式数值描述
MOVE_None
0无移动处理
MOVE_Walking
1带地面检测和台阶攀爬的地面移动
MOVE_NavWalking
2由导航网格投影驱动的行走
MOVE_Falling
3空中状态——重力、空中控制、落地检测
MOVE_Swimming
4带浮力的流体移动
MOVE_Flying
5自由3D移动,无重力
MOVE_Custom
6用户自定义;通过
uint8
子模式分发到
PhysCustom
MOVE_MAX
7哨兵值
使用
SetMovementMode(EMovementMode, uint8 CustomMode = 0)
切换模式。每次模式切换后,CMC会调用
OnMovementModeChanged(PreviousMode, PreviousCustomMode)
,这是处理自定义模式进入/退出逻辑的正确位置。

Phys* Movement Pipeline

Phys*移动管线

Every tick, CMC processes movement through a strict pipeline. Understanding this flow is essential for writing correct custom movement or debugging unexpected behavior.
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
:
  • PhysWalking(float deltaTime, int32 Iterations)
    — ground movement
  • PhysNavWalking(float deltaTime, int32 Iterations)
    — navmesh-projected walking
  • PhysFalling(float deltaTime, int32 Iterations)
    — airborne/gravity
  • PhysSwimming(float deltaTime, int32 Iterations)
    — fluid movement
  • PhysFlying(float deltaTime, int32 Iterations)
    — free flight
  • PhysCustom(float deltaTime, int32 Iterations)
    — your code here
Inside each
Phys*
function, two core methods do the heavy lifting:
CalcVelocity
computes the velocity for this frame:
cpp
// BlueprintCallable
void CalcVelocity(float DeltaTime, float Friction, bool bFluid, float BrakingDeceleration);
SafeMoveUpdatedComponent
moves the capsule and resolves penetration:
cpp
virtual bool SafeMoveUpdatedComponent(
    const FVector& Delta,
    const FQuat& NewRotation,
    bool bSweep,
    FHitResult& OutHit,
    ETeleportType Teleport = ETeleportType::None
);
It wraps
MoveUpdatedComponent
and automatically handles depenetration if the move results in an overlap. Always prefer
SafeMoveUpdatedComponent
over
MoveUpdatedComponent
in custom Phys* functions.
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
PhysWalking
,
ComputeGroundMovementDelta
(virtual) adjusts the velocity delta to follow the floor slope — it projects horizontal input onto the floor plane so the character walks along inclines rather than into them.
See
references/movement-pipeline.md
for the full flow diagram and per-mode breakdown.

每帧,CMC都会通过严格的管线处理移动。理解这一流程对于编写正确的自定义移动逻辑或调试异常行为至关重要。
PerformMovement(float DeltaTime)
是主要入口点(受保护)。它调用
StartNewPhysics()
,后者根据当前
EMovementMode
分发到对应的
Phys*
函数。每个
Phys*
函数都是
protected virtual
  • PhysWalking(float deltaTime, int32 Iterations)
    —— 地面移动
  • PhysNavWalking(float deltaTime, int32 Iterations)
    —— 导航网格投影行走
  • PhysFalling(float deltaTime, int32 Iterations)
    —— 空中/重力移动
  • PhysSwimming(float deltaTime, int32 Iterations)
    —— 流体移动
  • PhysFlying(float deltaTime, int32 Iterations)
    —— 自由飞行
  • PhysCustom(float deltaTime, int32 Iterations)
    —— 自定义代码实现处
每个
Phys*
函数内部,有两个核心方法负责主要工作:
CalcVelocity
计算当前帧的速度:
cpp
// BlueprintCallable
void CalcVelocity(float DeltaTime, float Friction, bool bFluid, float BrakingDeceleration);
SafeMoveUpdatedComponent
移动碰撞胶囊并解决穿透问题:
cpp
virtual bool SafeMoveUpdatedComponent(
    const FVector& Delta,
    const FQuat& NewRotation,
    bool bSweep,
    FHitResult& OutHit,
    ETeleportType Teleport = ETeleportType::None
);
它封装了
MoveUpdatedComponent
,如果移动导致重叠,会自动处理解穿透。在自定义Phys*函数中,始终优先使用
SafeMoveUpdatedComponent
而非
MoveUpdatedComponent
当扫查命中表面时,
SlideAlongSurface
会将移动沿表面投影。当在角落命中两个阻挡表面时,CMC会调用
TwoWallAdjust
UMovementComponent
的虚函数)来计算一个安全的移动方向以避开两面墙。在
PhysWalking
中,
ComputeGroundMovementDelta
(虚函数)会调整速度增量以适应地面坡度——它将水平输入投影到地面平面,使角色沿斜坡行走而非撞向斜坡。
完整的流程图和各模式的详细分解可查看
references/movement-pipeline.md

Floor Detection

地面检测

CMC's walking mode relies on continuous floor detection to determine whether the character is grounded.
CMC的行走模式依赖持续的地面检测来判断角色是否处于地面。

FFindFloorResult

FFindFloorResult

cpp
struct FFindFloorResult
{
    uint32 bBlockingHit : 1;    // Sweep hit something
    uint32 bWalkableFloor : 1;  // Hit surface passes walkability test
    uint32 bLineTrace : 1;      // Result came from line trace (not sweep)
    float FloorDist;             // Distance from capsule bottom to floor
    float LineDist;              // Distance from line trace
    FHitResult HitResult;        // Full hit result data

    bool IsWalkableFloor() const { return bBlockingHit && bWalkableFloor; }
};
cpp
struct FFindFloorResult
{
    uint32 bBlockingHit : 1;    // 扫查命中物体
    uint32 bWalkableFloor : 1;  // 命中表面通过可行走测试
    uint32 bLineTrace : 1;      // 结果来自线迹检测(而非扫查)
    float FloorDist;             // 胶囊底部到地面的距离
    float LineDist;              // 线迹检测的距离
    FHitResult HitResult;        // 完整的命中结果数据

    bool IsWalkableFloor() const { return bBlockingHit && bWalkableFloor; }
};

Floor Detection Methods

地面检测方法

FindFloor
is the primary method:
cpp
void FindFloor(
    const FVector& CapsuleLocation,
    FFindFloorResult& OutFloorResult,
    bool bCanUseCachedLocation,
    const FHitResult* DownwardSweepResult = nullptr
);
It delegates to
ComputeFloorDist()
, which performs a downward capsule sweep followed by a line trace. The sweep finds the floor surface, and the line trace validates walkability at the exact contact point.
FindFloor
是主要方法:
cpp
void FindFloor(
    const FVector& CapsuleLocation,
    FFindFloorResult& OutFloorResult,
    bool bCanUseCachedLocation,
    const FHitResult* DownwardSweepResult = nullptr
);
它委托给
ComputeFloorDist()
,后者先执行向下的胶囊扫查,再执行线迹检测。扫查用于找到地面表面,线迹检测用于验证接触点的可行走性。

Walkable Floor Angle

可行走地面角度

Two linked properties control what counts as "walkable":
  • WalkableFloorAngle
    (default 44.765 degrees) — the maximum surface angle in degrees
  • WalkableFloorZ
    — the corresponding Z component of the surface normal (auto-calculated from the angle)
Set the angle, not the Z value directly.
SetWalkableFloorAngle()
updates both.

有两个关联属性控制“可行走”的判定:
  • WalkableFloorAngle
    (默认44.765度)—— 最大表面角度(以度为单位)
  • WalkableFloorZ
    —— 对应表面法线的Z分量(由角度自动计算)
请设置角度,而非直接设置Z值。
SetWalkableFloorAngle()
会同时更新这两个属性。

Custom Movement Modes

自定义移动模式

MOVE_Custom
with a
uint8
sub-mode is the standard way to add new movement types. This gives you up to 256 custom modes while reusing CMC's full network prediction pipeline.
带有
uint8
子模式的
MOVE_Custom
是添加新移动类型的标准方式。这允许你在复用CMC完整网络预测管线的同时,最多添加256种自定义模式。

Implementation Steps

实现步骤

  1. Define custom mode constants:
cpp
UENUM(BlueprintType)
enum class ECustomMovementMode : uint8
{
    WallRun = 0,
    Climb   = 1,
    Dash    = 2
};
  1. Override
    PhysCustom
    in your CMC subclass:
cpp
virtual void PhysCustom(float deltaTime, int32 Iterations) override;
  1. Enter the mode using
    SetMovementMode
    :
cpp
SetMovementMode(MOVE_Custom, static_cast<uint8>(ECustomMovementMode::WallRun));
  1. Handle transitions in
    OnMovementModeChanged
    :
cpp
virtual void OnMovementModeChanged(EMovementMode PrevMode, uint8 PrevCustomMode) override;
Inside
PhysCustom
, dispatch on
CustomMovementMode
and implement your simulation. Call
CalcVelocity
for acceleration,
SafeMoveUpdatedComponent
for capsule movement, and
SetMovementMode
when transitioning out.
See
references/cmc-extension-patterns.md
for a complete wall-run implementation.

  1. 定义自定义模式常量:
cpp
UENUM(BlueprintType)
enum class ECustomMovementMode : uint8
{
    WallRun = 0,
    Climb   = 1,
    Dash    = 2
};
  1. 在你的CMC子类中重写
    PhysCustom
cpp
virtual void PhysCustom(float deltaTime, int32 Iterations) override;
  1. 使用
    SetMovementMode
    进入模式:
cpp
SetMovementMode(MOVE_Custom, static_cast<uint8>(ECustomMovementMode::WallRun));
  1. OnMovementModeChanged
    中处理模式切换:
cpp
virtual void OnMovementModeChanged(EMovementMode PrevMode, uint8 PrevCustomMode) override;
PhysCustom
内部,根据
CustomMovementMode
分发逻辑并实现你的模拟。调用
CalcVelocity
处理加速度,
SafeMoveUpdatedComponent
处理胶囊移动,在切换模式时调用
SetMovementMode
完整的跑墙实现可查看
references/cmc-extension-patterns.md

Network Prediction

网络预测

CMC uses a client-side prediction and server reconciliation model. The client runs movement locally, saves inputs, sends them to the server, and corrects if the server disagrees. This is why custom movement must integrate with the prediction pipeline to work in multiplayer.
CMC使用客户端预测和服务器校正模型。客户端本地运行移动逻辑,保存输入,发送到服务器,并在服务器结果不一致时进行修正。这就是为什么自定义移动必须集成到预测管线中才能在多人游戏中正常工作。

FSavedMove_Character

FSavedMove_Character

Each client tick generates a saved move that records the input state:
Key fields:
bPressedJump
,
bWantsToCrouch
,
StartLocation
,
StartVelocity
,
SavedLocation
,
Acceleration
,
MaxSpeed
.
Key virtuals to override for custom data:
  • Clear()
    — reset your custom fields
  • SetMoveFor(ACharacter*, float, FVector const&, FNetworkPredictionData_Client_Character&)
    — capture your custom state from the CMC before the move executes
  • PrepMoveFor(ACharacter*)
    — restore your custom state before replaying a move
  • GetCompressedFlags() const
    — pack custom booleans into the
    uint8
    flags
  • CanCombineWith(const FSavedMovePtr&, ACharacter*, float)
    — return
    true
    only if two moves are identical (enables bandwidth optimization)
  • PostUpdate(ACharacter*, EPostUpdateMode)
    — called after the move executes
  • IsImportantMove(const FSavedMovePtr&)
    — prevent combining if this move carries significant state
客户端每帧都会生成一个保存的移动记录,用于记录输入状态:
关键字段:
bPressedJump
bWantsToCrouch
StartLocation
StartVelocity
SavedLocation
Acceleration
MaxSpeed
用于自定义数据的关键虚函数:
  • Clear()
    —— 重置自定义字段
  • SetMoveFor(ACharacter*, float, FVector const&, FNetworkPredictionData_Client_Character&)
    —— 在移动执行前从CMC捕获自定义状态
  • PrepMoveFor(ACharacter*)
    —— 在重放移动前恢复自定义状态
  • GetCompressedFlags() const
    —— 将自定义布尔值打包到
    uint8
    标志中
  • CanCombineWith(const FSavedMovePtr&, ACharacter*, float)
    —— 仅当两个移动完全相同时返回
    true
    (优化带宽)
  • PostUpdate(ACharacter*, EPostUpdateMode)
    —— 移动执行后调用
  • IsImportantMove(const FSavedMovePtr&)
    —— 如果移动携带重要状态,禁止合并

CompressedFlags

压缩标志

The
uint8
returned by
GetCompressedFlags
has a fixed layout:
FlagValuePurpose
FLAG_JumpPressed
0x01
Jump input
FLAG_WantsToCrouch
0x02
Crouch input
FLAG_Reserved_1
0x04
Engine reserved
FLAG_Reserved_2
0x08
Engine reserved
FLAG_Custom_0
0x10
Your custom flag
FLAG_Custom_1
0x20
Your custom flag
FLAG_Custom_2
0x40
Your custom flag
FLAG_Custom_3
0x80
Your custom flag
You get four custom bits. For more complex state, use
FCharacterNetworkMoveData
.
GetCompressedFlags
返回的
uint8
有固定布局:
标志数值用途
FLAG_JumpPressed
0x01
跳跃输入
FLAG_WantsToCrouch
0x02
蹲伏输入
FLAG_Reserved_1
0x04
引擎保留
FLAG_Reserved_2
0x08
引擎保留
FLAG_Custom_0
0x10
自定义标志
FLAG_Custom_1
0x20
自定义标志
FLAG_Custom_2
0x40
自定义标志
FLAG_Custom_3
0x80
自定义标志
你有4个自定义位。对于更复杂的状态,使用
FCharacterNetworkMoveData

FNetworkPredictionData_Client_Character

FNetworkPredictionData_Client_Character

Override
AllocateNewMove()
to return your custom
FSavedMove
subclass:
cpp
class FMyNetworkPredictionData : public FNetworkPredictionData_Client_Character
{
public:
    FMyNetworkPredictionData(const UCharacterMovementComponent& ClientMovement)
        : FNetworkPredictionData_Client_Character(ClientMovement) {}

    virtual FSavedMovePtr AllocateNewMove() override;
};
The CMC exposes this via
GetPredictionData_Client()
, which you override to lazy-init your custom prediction data class.
重写
AllocateNewMove()
以返回自定义的
FSavedMove
子类:
cpp
class FMyNetworkPredictionData : public FNetworkPredictionData_Client_Character
{
public:
    FMyNetworkPredictionData(const UCharacterMovementComponent& ClientMovement)
        : FNetworkPredictionData_Client_Character(ClientMovement) {}

    virtual FSavedMovePtr AllocateNewMove() override;
};
CMC通过
GetPredictionData_Client()
暴露此接口,你需要重写该函数以延迟初始化自定义预测数据类。

Modern Packed RPCs

现代打包RPC

UE5 uses packed move RPCs on
ACharacter
:
  • ServerMovePacked(FCharacterServerMovePackedBits)
    — client to server
  • ClientMoveResponsePacked(FCharacterMoveResponsePackedBits)
    — server to client
The old RPCs (
ServerMove
,
ServerMoveDual
,
ClientAdjustPosition
) are
DEPRECATED_CHARACTER_MOVEMENT_RPC
. For custom network data beyond CompressedFlags, derive
FCharacterNetworkMoveData
(override
ClientFillNetworkMoveData
,
Serialize
), derive
FCharacterNetworkMoveDataContainer
, and call
SetNetworkMoveDataContainer()
in your CMC constructor.
See
references/cmc-extension-patterns.md
for full FSavedMove and network data implementation templates.

UE5在
ACharacter
上使用打包移动RPC:
  • ServerMovePacked(FCharacterServerMovePackedBits)
    —— 客户端到服务器
  • ClientMoveResponsePacked(FCharacterMoveResponsePackedBits)
    —— 服务器到客户端
旧版RPC(
ServerMove
ServerMoveDual
ClientAdjustPosition
)已标记为
DEPRECATED_CHARACTER_MOVEMENT_RPC
。对于超出压缩标志的自定义网络数据,继承
FCharacterNetworkMoveData
(重写
ClientFillNetworkMoveData
Serialize
),继承
FCharacterNetworkMoveDataContainer
,并在CMC构造函数中调用
SetNetworkMoveDataContainer()
完整的FSavedMove和网络数据实现模板可查看
references/cmc-extension-patterns.md

Root Motion

根运动

Root motion allows animations or gameplay code to drive character movement directly. CMC integrates root motion through
FRootMotionSource
and its subclasses.
根运动允许动画或游戏玩法代码直接驱动角色移动。CMC通过
FRootMotionSource
及其子类集成根运动。

FRootMotionSource

FRootMotionSource

Base class fields:
  • Priority
    — higher priority sources override lower
  • LocalID
    — unique ID returned by
    ApplyRootMotionSource
  • InstanceName
    FName
    for retrieval and removal
  • Duration
    — total time in seconds; negative Duration means infinite (runs until explicitly removed)
  • AccumulateMode
    Override
    (replaces other sources) or
    Additive
    (stacks)
基类字段:
  • Priority
    —— 优先级高的源会覆盖优先级低的源
  • LocalID
    ——
    ApplyRootMotionSource
    返回的唯一ID
  • InstanceName
    —— 用于检索和移除的
    FName
  • Duration
    —— 总时长(秒);负值表示无限时长(需显式移除才会停止)
  • AccumulateMode
    ——
    Override
    (替换其他源)或
    Additive
    (叠加)

Subclasses

子类

ClassKey ParametersUse Case
FRootMotionSource_ConstantForce
Force
,
StrengthOverTime
Knockback, wind
FRootMotionSource_RadialForce
Location
,
Radius
,
Strength
Explosions, vortex
FRootMotionSource_MoveToForce
StartLocation
,
TargetLocation
Dash to fixed point
FRootMotionSource_MoveToDynamicForce
SetTargetLocation()
Homing dash
FRootMotionSource_JumpForce
Rotation
,
Distance
,
Height
Targeted jump arc
关键参数使用场景
FRootMotionSource_ConstantForce
Force
,
StrengthOverTime
击退、风力
FRootMotionSource_RadialForce
Location
,
Radius
,
Strength
爆炸、漩涡
FRootMotionSource_MoveToForce
StartLocation
,
TargetLocation
冲刺到固定点
FRootMotionSource_MoveToDynamicForce
SetTargetLocation()
追踪冲刺
FRootMotionSource_JumpForce
Rotation
,
Distance
,
Height
目标跳跃弧线

CMC Methods

CMC方法

cpp
// Returns uint16 LocalID for tracking
uint16 ApplyRootMotionSource(TSharedPtr<FRootMotionSource> Source);

// Retrieve by InstanceName
TSharedPtr<FRootMotionSource> GetRootMotionSource(FName InstanceName);

// Remove by InstanceName
void RemoveRootMotionSource(FName InstanceName);
Apply a constant knockback:
cpp
auto Knockback = MakeShared<FRootMotionSource_ConstantForce>();
Knockback->InstanceName = TEXT("Knockback");
Knockback->Duration = 0.3f;
Knockback->Force = KnockbackDirection * KnockbackStrength;
Knockback->AccumulateMode = ERootMotionAccumulateMode::Override;
CMC->ApplyRootMotionSource(Knockback);

cpp
// 返回用于追踪的uint16 LocalID
uint16 ApplyRootMotionSource(TSharedPtr<FRootMotionSource> Source);

// 通过InstanceName检索
TSharedPtr<FRootMotionSource> GetRootMotionSource(FName InstanceName);

// 通过InstanceName移除
void RemoveRootMotionSource(FName InstanceName);
应用持续击退效果:
cpp
auto Knockback = MakeShared<FRootMotionSource_ConstantForce>();
Knockback->InstanceName = TEXT("Knockback");
Knockback->Duration = 0.3f;
Knockback->Force = KnockbackDirection * KnockbackStrength;
Knockback->AccumulateMode = ERootMotionAccumulateMode::Override;
CMC->ApplyRootMotionSource(Knockback);

Key Properties

关键属性

PropertyDefaultDescription
MaxWalkSpeed
600Maximum ground speed
MaxAcceleration
Rate of speed change
GravityScale
1.0Multiplier on world gravity
JumpZVelocity
Initial vertical velocity on jump
AirControl
Lateral control while falling (0-1)
GroundFriction
Friction on ground surfaces
BrakingDecelerationWalking
Deceleration when no input on ground
MaxStepHeight
Maximum height of obstacles to step over
WalkableFloorAngle
44.765Max walkable surface angle in degrees
MaxWalkSpeedCrouched
Speed while crouching
MaxSwimSpeed
Maximum speed in water
MaxFlySpeed
Maximum speed when flying
MaxCustomMovementSpeed
Speed cap for custom modes
bOrientRotationToMovement
Rotate character toward movement direction
bUseControllerDesiredRotation
Smoothly rotate toward controller rotation
NetworkSmoothingMode
Simulated proxy interpolation mode
MaxSimulationTimeStep
Cap on sub-step delta for stability
MaxSimulationIterations
Max physics iterations per frame
bUseRVOAvoidance
falseEnable RVO (reciprocal velocity obstacle) avoidance
AvoidanceGroup
FNavAvoidanceMask
— group membership for avoidance filtering
AvoidanceWeight
float — higher weight yields right-of-way to other agents
属性默认值描述
MaxWalkSpeed
600最大地面移动速度
MaxAcceleration
速度变化率
GravityScale
1.0世界重力的乘数
JumpZVelocity
跳跃时的初始垂直速度
AirControl
下落时的横向控制(0-1)
GroundFriction
地面表面的摩擦力
BrakingDecelerationWalking
地面无输入时的减速度
MaxStepHeight
可攀爬的障碍物最大高度
WalkableFloorAngle
44.765最大可行走表面角度(度)
MaxWalkSpeedCrouched
蹲伏时的速度
MaxSwimSpeed
水中最大速度
MaxFlySpeed
飞行时的最大速度
MaxCustomMovementSpeed
自定义模式的速度上限
bOrientRotationToMovement
使角色朝向移动方向旋转
bUseControllerDesiredRotation
平滑地朝向控制器旋转方向
NetworkSmoothingMode
模拟代理的插值模式
MaxSimulationTimeStep
子步delta的上限,保证稳定性
MaxSimulationIterations
每帧最大物理迭代次数
bUseRVOAvoidance
false启用RVO(相对速度障碍物)避让
AvoidanceGroup
FNavAvoidanceMask
—— 避让过滤的组归属
AvoidanceWeight
float —— 权重越高,越优先获得通行权

Rotation

旋转

bOrientRotationToMovement
and
bUseControllerDesiredRotation
are mutually exclusive in practice. The first rotates the character toward its velocity direction (third-person), the second smoothly rotates toward where the controller is facing (strafing shooter). Set one, not both.
bOrientRotationToMovement
bUseControllerDesiredRotation
在实际使用中互斥。前者使角色朝向速度方向(第三人称视角),后者使角色平滑朝向控制器指向的方向( Strafing射击游戏)。请仅设置其中一个。

Gravity Direction (UE 5.4+)

重力方向(UE 5.4+)

cpp
virtual void SetGravityDirection(const FVector& GravityDir);
FVector GetGravityDirection() const;
bool HasCustomGravity() const;
// Transform helpers (fields are protected — access via accessors)
FQuat GetWorldToGravityTransform() const;
FQuat GetGravityToWorldTransform() const;
Custom gravity reorients the entire movement simulation. Walking, falling, and floor detection all respect the gravity direction when
HasCustomGravity()
returns
true
.

cpp
virtual void SetGravityDirection(const FVector& GravityDir);
FVector GetGravityDirection() const;
bool HasCustomGravity() const;
// 变换助手(字段受保护——通过访问器访问)
FQuat GetWorldToGravityTransform() const;
FQuat GetGravityToWorldTransform() const;
自定义重力会重新调整整个移动模拟。当
HasCustomGravity()
返回
true
时,行走、下落和地面检测都会遵循重力方向。

ACharacter API

ACharacter API

ACharacter
provides high-level movement actions that delegate to CMC:
ACharacter
提供高层移动动作,委托给CMC处理:

Jump

跳跃

cpp
void Jump();           // Sets bPressedJump, CMC handles velocity
void StopJumping();    // Clears jump input
bool CanJump() const;  // Checks CanJumpInternal
Properties:
bPressedJump
,
JumpMaxHoldTime
,
JumpMaxCount
,
JumpCurrentCount
.
DoJump(bool bReplayingMoves, float DeltaTime)
is the internal method called by CMC to apply the jump velocity. In UE 5.5+ it takes two parameters; the old
DoJump(bool)
is deprecated.
cpp
void Jump();           // 设置bPressedJump,CMC处理速度
void StopJumping();    // 清除跳跃输入
bool CanJump() const;  // 检查CanJumpInternal
属性:
bPressedJump
JumpMaxHoldTime
JumpMaxCount
JumpCurrentCount
DoJump(bool bReplayingMoves, float DeltaTime)
是CMC调用的内部方法,用于应用跳跃速度。UE 5.5+版本有两个参数;旧版
DoJump(bool)
已被弃用。

Crouch

蹲伏

cpp
void Crouch(bool bClientSimulation = false);
void UnCrouch(bool bClientSimulation = false);
bIsCrouched
is the replicated state. CMC handles capsule resizing and checks for clearance before uncrouching. Note:
CrouchedHalfHeight
on CMC is deprecated as of UE 5.0 — use
SetCrouchedHalfHeight()
/
GetCrouchedHalfHeight()
on the CMC instead.
cpp
void Crouch(bool bClientSimulation = false);
void UnCrouch(bool bClientSimulation = false);
bIsCrouched
是复制状态。CMC处理胶囊尺寸调整,并在站起前检查空间是否足够。注意:UE 5.0起,CMC上的
CrouchedHalfHeight
已被弃用——请改用CMC上的
SetCrouchedHalfHeight()
/
GetCrouchedHalfHeight()

LaunchCharacter

角色发射

cpp
void LaunchCharacter(FVector LaunchVelocity, bool bXYOverride, bool bZOverride);
When
bXYOverride
is
true
, replaces XY velocity entirely. When
false
, adds to existing velocity. Same logic for
bZOverride
on the Z axis. Automatically transitions to
MOVE_Falling
.
cpp
void LaunchCharacter(FVector LaunchVelocity, bool bXYOverride, bool bZOverride);
bXYOverride
true
时,完全替换XY速度;为
false
时,叠加到现有速度上。Z轴的逻辑相同。会自动切换到
MOVE_Falling
模式。

Landed

落地

cpp
virtual void Landed(const FHitResult& Hit);
Called when the character lands after falling. Override this for landing effects, damage, or animation triggers.
cpp
virtual void Landed(const FHitResult& Hit);
角色从空中落地时调用。可重写此函数以实现落地效果、伤害或动画触发。

Accessors

访问器

cpp
UCharacterMovementComponent* GetCharacterMovement() const;
UCapsuleComponent* GetCapsuleComponent() const;
USkeletalMeshComponent* GetMesh() const;

cpp
UCharacterMovementComponent* GetCharacterMovement() const;
UCapsuleComponent* GetCapsuleComponent() const;
USkeletalMeshComponent* GetMesh() const;

Common Mistakes

常见错误

Modifying velocity directly instead of using CalcVelocity:
cpp
// WRONG: Bypasses friction, braking, and acceleration curves
Velocity = GetLastInputVector() * MaxWalkSpeed;

// RIGHT: Let CMC handle physics
CalcVelocity(DeltaTime, GroundFriction, false, BrakingDecelerationWalking);
Forgetting to call Super in PhysCustom:
cpp
// WRONG: Skips base class bookkeeping
void UMyCMC::PhysCustom(float DT, int32 Iter)
{
    MyCustomLogic(DT, Iter);
}

// RIGHT: Call Super first (base PhysCustom is empty but future-proofs)
void UMyCMC::PhysCustom(float DT, int32 Iter)
{
    Super::PhysCustom(DT, Iter);
    MyCustomLogic(DT, Iter);
}
Not saving custom state in FSavedMove: Custom movement flags that are not captured in
SetMoveFor
and restored in
PrepMoveFor
will be lost during server correction replays, causing desyncs.
Using MoveUpdatedComponent instead of SafeMoveUpdatedComponent:
MoveUpdatedComponent
does not resolve penetration. In custom Phys* functions, always use
SafeMoveUpdatedComponent
to prevent the character from getting stuck inside geometry.
Setting both rotation flags:
bOrientRotationToMovement
and
bUseControllerDesiredRotation
conflict. The character oscillates between two desired rotations each frame. Pick one based on your camera style.
Using deprecated old-style RPCs:
ServerMove
,
ServerMoveDual
,
ClientAdjustPosition
are
DEPRECATED_CHARACTER_MOVEMENT_RPC
. Use the packed RPC pipeline and
FCharacterNetworkMoveData
for custom data.

直接修改速度而非使用CalcVelocity:
cpp
// 错误:绕过了摩擦力、制动和加速度曲线
Velocity = GetLastInputVector() * MaxWalkSpeed;

// 正确:让CMC处理物理逻辑
CalcVelocity(DeltaTime, GroundFriction, false, BrakingDecelerationWalking);
在PhysCustom中忘记调用Super:
cpp
// 错误:跳过了基类的簿记工作
void UMyCMC::PhysCustom(float DT, int32 Iter)
{
    MyCustomLogic(DT, Iter);
}

// 正确:先调用Super(基类PhysCustom为空,但这样做可兼容未来版本)
void UMyCMC::PhysCustom(float DT, int32 Iter)
{
    Super::PhysCustom(DT, Iter);
    MyCustomLogic(DT, Iter);
}
未在FSavedMove中保存自定义状态: 未在
SetMoveFor
中捕获并在
PrepMoveFor
中恢复的自定义移动标志,会在服务器校正重放时丢失,导致不同步。
使用MoveUpdatedComponent而非SafeMoveUpdatedComponent:
MoveUpdatedComponent
不会解决穿透问题。在自定义Phys*函数中,始终使用
SafeMoveUpdatedComponent
以防止角色卡在几何体内部。
同时设置两个旋转标志:
bOrientRotationToMovement
bUseControllerDesiredRotation
会冲突。角色每帧会在两个期望旋转之间振荡。请根据你的相机风格选择其中一个。
使用已弃用的旧版RPC:
ServerMove
ServerMoveDual
ClientAdjustPosition
已标记为
DEPRECATED_CHARACTER_MOVEMENT_RPC
。对于自定义数据,请使用打包RPC管线和
FCharacterNetworkMoveData

Reference Files

参考文件

  • references/cmc-extension-patterns.md
    — Complete CMC subclass templates: custom FSavedMove, prediction data, GetPredictionData_Client, wall-run PhysCustom, and custom network move data
  • references/movement-pipeline.md
    — Phys* flow diagrams, floor detection chain, step-up logic, PhysWalking/PhysFalling breakdowns, and root motion replication flow
  • references/cmc-extension-patterns.md
    —— 完整的CMC子类模板:自定义FSavedMove、预测数据、GetPredictionData_Client、跑墙PhysCustom和自定义网络移动数据
  • references/movement-pipeline.md
    —— Phys*流程图、地面检测链、台阶攀爬逻辑、PhysWalking/PhysFalling分解以及根运动复制流程

Related Skills

相关技能

  • ue-networking-replication
    — Replication fundamentals, RPCs, net roles; CMC prediction builds on this
  • ue-animation-system
    — Root motion from AnimMontage, animation-driven movement
  • ue-physics-collision
    — Sweep queries, collision channels used by CMC floor detection
  • ue-gameplay-abilities
    — GAS abilities that trigger movement modes or root motion
  • ue-ai-navigation
    — NavMesh integration, MOVE_NavWalking, RVO avoidance
  • ue-input-system
    — Enhanced Input feeding movement input to CMC
  • ue-actor-component-architecture
    — Component subobject patterns for CMC subclasses
  • ue-networking-replication
    —— 复制基础、RPC、网络角色;CMC预测基于此构建
  • ue-animation-system
    —— 来自AnimMontage的根运动、动画驱动的移动
  • ue-physics-collision
    —— 扫查查询、CMC地面检测使用的碰撞通道
  • ue-gameplay-abilities
    —— 触发移动模式或根运动的GAS能力
  • ue-ai-navigation
    —— NavMesh集成、MOVE_NavWalking、RVO避让
  • ue-input-system
    —— 增强输入系统向CMC提供移动输入
  • ue-actor-component-architecture
    —— CMC子类的组件子对象模式