自动化与脚本
在虚幻引擎中扩展或调试角色移动(CharacterMovem…
适用于处理 UE 角色移动、CMC 自定义移动模式、网络预测、根运动与地面检测等场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在虚幻引擎中扩展或调试角色移动(Char特定
解决思路
- 先阅读 `.agents/ue-project-context.md`,确认项目使用 `ACharacter` 还是自定义 Pawn、UE 版本(UE 5.4+ 支持 `GravityDirection`,UE 5.5 修改了 `DoJump` 签名)、是否涉及多人联机、以及是否已有 CMC 子类或自定义移动模式。
- 向开发者确认:是扩展 `UCharacterMovementComponent` 还是配置默认组件;是否需要自定义移动模式(如跑墙、攀爬、冲刺);是否多人联机且自定义能力是否需要网络预测;是否集成动画或游戏代码的根运动;是否需要自定义重力方向(UE 5.4+)。
- 理解 CMC 的类层级:`UMovementComponent` -> `UNavMovementComponent` -> `UPawnMovementComponent` -> `UCharacterMovementComponent`,它同时实现 `IRVOAvoidanceInterface` 和 `INetworkPredictionInterface`,声明为 `UCLASS(MinimalAPI)`。
- 通过 `SetMovementMode(EMovementMode, uint8 CustomMode = 0)` 切换移动模式;每次切换后 CMC 会调用 `OnMovementModeChanged(PreviousMode, PreviousCustomMode)`,在此处理自定义模式的进入/退出逻辑。
- 掌握 `PerformMovement(float DeltaTime)` 主入口,它调用 `StartNewPhysics()` 根据当前 `EMovementMode` 分发到对应的 `Phys*` 函数:`PhysWalking`、`PhysNavWalking`、`PhysFalling`、`PhysSwimming`、`PhysFlying`、`PhysCustom`。
- 在每个 `Phys*` 函数内使用 `CalcVelocity(float DeltaTime, float Friction, bool bFluid, float BrakingDeceleration)` 计算本帧速度,使用 `SafeMoveUpdatedComponent(const FVector& Delta, const FQuat& NewRotation, bool bSweep, FHitResult& OutHit, ETeleportType Teleport = ETeleportType::None)` 移动胶囊体并解决穿透。
- 当扫掠命中表面时使用 `SlideAlongSurface` 沿表面投影移动;当在角落命中两个阻挡表面时,CMC 调用 `TwoWallAdjust` 计算安全移动方向;在 `PhysWalking` 中 `ComputeGroundMovementDelta` 调整速度增量以沿地面斜坡行走。
- 使用 `FindFloor(const FVector& CapsuleLocation, FFindFloorResult& OutFloorResult, bool bCanUseCachedLocation, const FHitResult* DownwardSweepResult = nullptr)` 进行地面检测,它委托给 `ComputeFloorDist()` 执行向下胶囊扫掠加线检测。
- 通过 `WalkableFloorAngle`(默认 44.765 度)控制可行走表面角度,使用 `SetWalkableFloorAngle()` 同时更新角度和对应的 `WalkableFloorZ`,不要直接设置 Z 值。
- 实现自定义移动模式:定义 `UENUM(BlueprintType)` 枚举自定义模式常量;重写 `virtual void PhysCustom(float deltaTime, int32 Iterations) override`;用 `SetMovementMode(MOVE_Custom, static_cast<uint8>(ECustomMovementMode::WallRun))` 进入模式;重写 `OnMovementModeChanged` 处理转换;在 `PhysCustom` 中根据 `CustomMovementMode` 分发并调用 `CalcVelocity`、`SafeMoveUpdatedComponent`,退出时调用 `SetMovementMode`。
- 为多人联机实现网络预测:重写 `FSavedMove_Character` 的 `Clear()`、`SetMoveFor(ACharacter*, float, FVector const&, FNetworkPredictionData_Client_Character&)`、`PrepMoveFor(ACharacter*)`、`GetCompressedFlags() const`、`CanCombineWith(const FSavedMovePtr&, ACharacter*, float)`、`PostUpdate(ACharacter*, EPostUpdateMode)`、`IsImportantMove(const FSavedMovePtr&)`。
- 使用 `GetCompressedFlags()` 返回的 `uint8` 中的四个自定义位:`FLAG_Custom_0`(0x10)、`FLAG_Custom_1`(0x20)、`FLAG_Custom_2`(0x40)、`FLAG_Custom_3`(0x80);更复杂状态使用 `FCharacterNetworkMoveData`。
- 重写 `AllocateNewMove()` 返回自定义 `FSavedMove` 子类,并重写 `GetPredictionData_Client()` 懒初始化自定义预测数据类。
- 对于超出 CompressedFlags 的自定义网络数据,派生 `FCharacterNetworkMoveData`(重写 `ClientFillNetworkMoveData`、`Serialize`),派生 `FCharacterNetworkMoveDataContainer`,并在 CMC 构造函数中调用 `SetNetworkMoveDataContainer()`。
- 使用 UE5 的打包 RPC:`ServerMovePacked(FCharacterServerMovePackedBits)` 和 `ClientMoveResponsePacked(FCharacterMoveResponsePackedBits)`;避免使用已弃用的 `ServerMove`、`ServerMoveDual`、`ClientAdjustPosition`。
- 集成根运动:使用 `ApplyRootMotionSource(TSharedPtr<FRootMotionSource> Source)` 返回 `uint16 LocalID`;用 `GetRootMotionSource(FName InstanceName)` 获取;用 `RemoveRootMotionSource(FName InstanceName)` 移除。
- 选择合适的 `FRootMotionSource` 子类:`FRootMotionSource_ConstantForce`(击退、风)、`FRootMotionSource_RadialForce`(爆炸、漩涡)、`FRootMotionSource_MoveToForce`(冲刺到固定点)、`FRootMotionSource_MoveToDynamicForce`(追踪冲刺)、`FRootMotionSource_JumpForce`(定向跳跃弧线)。
- 配置根运动源字段:`Priority`(高优先级覆盖低优先级)、`LocalID`、`InstanceName`、`Duration`(负值表示无限直到显式移除)、`AccumulateMode`(`Override` 替换其他源或 `Additive` 叠加)。
- 设置旋转模式:`bOrientRotationToMovement` 和 `bUseControllerDesiredRotation` 互斥,前者朝速度方向旋转(第三人称),后者朝控制器朝向平滑旋转(射击游戏),只设置一个。
- 使用 UE 5.4+ 自定义重力:`SetGravityDirection(const FVector& GravityDir)`、`GetGravityDirection()`、`HasCustomGravity()`、`GetWorldToGravityTransform()`、`GetGravityToWorldTransform()`。
- 使用 `ACharacter` 高级 API:`Jump()`、`StopJumping()`、`CanJump()`;`Crouch(bool bClientSimulation = false)`、`UnCrouch(bool bClientSimulation = false)`;`LaunchCharacter(FVector LaunchVelocity, bool bXYOverride, bool bZOverride)`;重写 `Landed(const FHitResult& Hit)`。
- 使用访问器:`GetCharacterMovement()`、`GetCapsuleComponent()`、`GetMesh()`。
- 避免常见错误:不要直接修改 `Velocity`,应使用 `CalcVelocity`;在 `PhysCustom` 中先调用 `Super::PhysCustom(DT, Iter)`;在 `SetMoveFor` 和 `PrepMoveFor` 中保存/恢复自定义状态;在自定义 `Phys*` 中使用 `SafeMoveUpdatedComponent` 而非 `MoveUpdatedComponent`;不要同时设置两个旋转标志;不要使用已弃用的旧式 RPC。
适用边界 · 注意事项
- 不涉及虚幻引擎角色移动系统的项目不适用。
- 非多人联机项目可跳过网络预测相关步骤。
- 不使用 UE 5.4+ 的项目无法使用自定义重力方向功能。