UE5.7 CMC PhysWalking:从键盘输入到一帧移动与网络同步
生成时间:2026-05-19
仓库:E:/UE5.7
分析范围:UCharacterMovementComponent 传统游戏线程路径,以 MOVE_Walking / PhysWalking 为主,覆盖本地预测、服务器重放校验、客户端纠错重放、模拟代理平滑。
核心结论
AddMovementInput本身不移动角色,只把输入累积到APawn::ControlInputVector;真正消费发生在UCharacterMovementComponent::TickComponent开头。- 本地玩家在客户端是
ROLE_AutonomousProxy:同一帧先本地预测PerformMovement,再把FSavedMove_Character通过ServerMove/ServerMovePacked发给服务器。 - 服务器不会直接采用客户端最终位置,而是用客户端上报的时间戳、压缩 flags、Acceleration 重新执行
MoveAutonomous -> PerformMovement -> PhysWalking,再比较误差并 ack 或 correction。 - 客户端收到 correction 后会先把 capsule 修到服务器状态,再在下一次 CMC tick 开头重放未确认的 saved moves,因此玩家看到的是“预测即时 + 必要时橡皮筋”。
- 其他客户端上的该角色通常是
ROLE_SimulatedProxy,不跑输入预测,依赖 replicated movement、SimulateMovement和 mesh 平滑。
一帧主时间线
T0:键盘输入进入玩家代码
Enhanced Input 或传统输入系统最终通常会调用项目里的移动函数,例如:
AddMovementInput(Direction, AxisValue);
引擎侧入口是:
APawn::AddMovementInput:Engine/Source/Runtime/Engine/Private/Pawn.cpp:799UPawnMovementComponent::AddInputVector:Engine/Source/Runtime/Engine/Private/Components/PawnMovementComponent.cpp:64APawn::Internal_AddMovementInput:Engine/Source/Runtime/Engine/Private/Pawn.cpp:838
关键行为:
ControlInputVector += WorldAccel;
所以本阶段只是累积输入,不进行碰撞、不改位置、不发 RPC。
T1:CMC Tick 消费输入
UCharacterMovementComponent::TickComponent 是角色移动组件每帧主入口:
TickComponent:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:1622- 非 async 路径消费输入:
CharacterMovementComponent.cpp:1634 APawn::Internal_ConsumeMovementInputVector:Engine/Source/Runtime/Engine/Private/Pawn.cpp:846
消费时:
LastControlInputVector = ControlInputVector;
ControlInputVector = FVector::ZeroVector;
调试时如果在 Tick 后看 ControlInputVector,它通常已经被清零;应看 LastControlInputVector 或后续 CMC 的 Acceleration。
T2:根据网络角色选择移动分支
TickComponent 中的关键角色分支:
- 非模拟代理分支:
CharacterMovementComponent.cpp:1703 - 自主客户端先处理服务器纠错:
CharacterMovementComponent.cpp:1708、:1714 - 执行本地受控移动:
CharacterMovementComponent.cpp:1729 - 模拟代理分支:
CharacterMovementComponent.cpp:1756、:1765
简化逻辑:
LocalRole > SimulatedProxy:if AutonomousProxy client and has correction:ClientUpdatePositionAfterServerUpdate()if locally controlled:ControlledCharacterMove(InputVector, DeltaTime)else if server owns remote autonomous proxy:ServerAutonomousProxyTick / based movementLocalRole == SimulatedProxy:SimulatedTick(DeltaTime)
输入如何变成 Acceleration
入口:
UCharacterMovementComponent::ControlledCharacterMove:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:6340
关键步骤:
CharacterOwner->CheckJumpInput(DeltaSeconds):先处理跳跃,降低输入延迟。Acceleration = ScaleInputAcceleration(ConstrainInputAcceleration(InputVector)):把输入向量约束并缩放为移动加速度。AnalogInputModifier = ComputeAnalogInputModifier():计算模拟输入强度。- 按角色分支:
- Authority:直接
PerformMovement(DeltaSeconds),见CharacterMovementComponent.cpp:6354、:6356 - AutonomousProxy 客户端:进入
ReplicateMoveToServer(DeltaSeconds, Acceleration),见CharacterMovementComponent.cpp:6358、:6360
- Authority:直接
PerformMovement 主流程
入口:
UCharacterMovementComponent::PerformMovement:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:2703
主职责不是某一种移动模式,而是统一的一帧移动管线:
- 校验组件有效性、移动模式、物理模拟状态。
MaybeUpdateBasedMovement:处理站在移动平台等 base movement。- 清理/准备 Root Motion Source。
- 保存旧速度/旧位置。
ApplyAccumulatedForces、HandlePendingLaunch。UpdateCharacterStateBeforeMovement。- Root Motion 转速度或覆盖速度。
CharacterOwner->ClearJumpInput。UpdateVelocityBeforeMovement。StartNewPhysics(DeltaSeconds, 0):按移动模式进入具体物理函数,见CharacterMovementComponent.cpp:2959。UpdateCharacterStateAfterMovement:CharacterMovementComponent.cpp:2967PhysicsRotation:CharacterMovementComponent.cpp:2971OnMovementUpdated:CharacterMovementComponent.cpp:3028MaybeSaveBaseLocation/SaveBaseLocation:CharacterMovementComponent.cpp:3040UpdateComponentVelocity:CharacterMovementComponent.cpp:3042- Authority 端若移动导致 adaptive replication 被节流,可能取消节流。
- 更新
LastUpdateLocation、LastUpdateRotation、LastUpdateVelocity。
移动模式分发入口:
UCharacterMovementComponent::StartNewPhysics:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:3454
MOVE_Walking 最终进入:
UCharacterMovementComponent::PhysWalking:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:5554
PhysWalking 内部流程
PhysWalking 是 Walking 模式下真正做地面移动、斜坡、台阶、Floor 检测的核心。
1. 入口保护
锚点:CharacterMovementComponent.cpp:5554
主要保护:
deltaTime < MIN_TICK_TIME直接返回。- 没有 controller 且不允许无 controller 跑物理、无 root motion、非 simulated proxy 时,清零
Acceleration和Velocity返回。 - UpdatedComponent 不支持 query collision 时维持 Walking 并返回。
2. 子步循环
锚点:CharacterMovementComponent.cpp:5586
Walking 并非必然只算一次,会按 remainingTime 和 MaxSimulationIterations 做子步:
while remainingTime >= MIN_TICK_TIME and Iterations < MaxSimulationIterations:timeTick = GetSimulationTimeStep(remainingTime, Iterations)remainingTime -= timeTick
每个子步会保存:
OldBasePreviousBaseLocationOldLocationOldFloorOldVelocity
这些变量是调试台阶、斜坡、离地和回滚时的关键。
3. 水平速度和加速度投影
锚点:
MaintainHorizontalGroundVelocity调用:CharacterMovementComponent.cpp:5609Acceleration = FVector::VectorPlaneProject(...):CharacterMovementComponent.cpp:5611- 函数定义:
CharacterMovementComponent.cpp:5536
UE5.7 支持任意重力方向,因此“水平”不是简单清 Z,而是投影到垂直于 GravityDirection 的平面。
4. 速度积分
锚点:
CalcVelocity调用:CharacterMovementComponent.cpp:5617CalcVelocity定义:CharacterMovementComponent.cpp:3786ApplyRootMotionToVelocity调用:CharacterMovementComponent.cpp:5621
主逻辑:
若没有动画 root motion、没有 override root motion、不是特殊 ledge move:CalcVelocity(timeTick, GroundFriction, false, GetMaxBrakingDeceleration())
ApplyRootMotionToVelocity(timeTick)
CalcVelocity 会综合:
AccelerationGroundFriction- braking deceleration
- requested velocity
- analog input modifier
5. 贴地移动
锚点:
- 计算
Delta = timeTick * Velocity:CharacterMovementComponent.cpp:5632 MoveAlongFloor调用:CharacterMovementComponent.cpp:5645MoveAlongFloor定义:CharacterMovementComponent.cpp:5457ComputeGroundMovementDelta定义:CharacterMovementComponent.cpp:5394StepUp定义:CharacterMovementComponent.cpp:7450
MoveAlongFloor 会根据当前 floor/ramp 法线把水平位移转换为贴地/沿坡位移,遇到阻挡后可能:
- slide along surface
- 尝试
StepUp - 计算 step down
- 填充
FStepDownResult
6. Floor 更新与离地判定
锚点:
- 使用
StepDownResult或FindFloor:CharacterMovementComponent.cpp:5667 FindFloor调用:CharacterMovementComponent.cpp:5675FindFloor定义:CharacterMovementComponent.cpp:7100- ledge 检查:
CharacterMovementComponent.cpp:5679 StartFalling相关分支:CharacterMovementComponent.cpp:5726
移动后 CMC 会更新 CurrentFloor。如果 floor 不可行走,或走到 ledge 且不能走下边缘,会尝试:
GetLedgeMove找替代方向。RevertMove回滚。CheckFall/StartFalling切到 Falling。
Walking 同步问题很多不是速度错误,而是客户端和服务器对 CurrentFloor、ledge、base 或 step up/down 的结果不同。
7. 调整地面高度和 MovementBase
锚点:
AdjustFloorHeight调用:CharacterMovementComponent.cpp:5731SetBaseFromFloor调用:CharacterMovementComponent.cpp:5732AdjustFloorHeight定义:CharacterMovementComponent.cpp:6194
AdjustFloorHeight 会把 capsule 与地面的距离维持在合理范围;SetBaseFromFloor 会更新角色站立的 movement base。
8. 根据实际位移回写速度
锚点:
Velocity = (UpdatedComponent->GetComponentLocation() - OldLocation) / timeTick:CharacterMovementComponent.cpp:5772- 末尾再次
MaintainHorizontalGroundVelocity:CharacterMovementComponent.cpp:5785
这意味着 Walking 最终速度可能不是单纯由 CalcVelocity 得到,而会被碰撞、台阶、地面修正后的实际位移反推覆盖。
AutonomousProxy 客户端预测与 ServerMove 发送
入口:
UCharacterMovementComponent::ReplicateMoveToServer:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:8789
核心步骤:
- 检查
AcknowledgedPawn,避免 controller 未同步时刷 reliable buffer:CharacterMovementComponent.cpp:8794 - 获取
FNetworkPredictionData_Client_Character:CharacterMovementComponent.cpp:8808 - 更新时间戳与 DeltaTime:
CharacterMovementComponent.cpp:8815 - 查找 oldest important unacked move:
CharacterMovementComponent.cpp:8817 - 创建
FSavedMove_Character:CharacterMovementComponent.cpp:8836 NewMove->SetMoveFor(...):CharacterMovementComponent.cpp:8843- 定义:
CharacterMovementComponent.cpp:12502
- 定义:
- 尝试与
PendingMove合并:CharacterMovementComponent.cpp:8846CanCombineWith定义:CharacterMovementComponent.cpp:12823
- 约束将要发送给服务器的
Acceleration:CharacterMovementComponent.cpp:8900 - 本地执行预测移动:
CharacterMovementComponent.cpp:8906 NewMove->PostUpdate(...):CharacterMovementComponent.cpp:8908- 保存到
ClientData->SavedMoves:CharacterMovementComponent.cpp:8914 - 可能延迟发送以便合包:
CharacterMovementComponent.cpp:8916 - 调用 packed 或 legacy RPC:
CharacterMovementComponent.cpp:8965、:8971
关键点:客户端预测移动发生在 RPC 往返之前,因此本地玩家按键后会立即动。
Packed RPC 路径
锚点:
CallServerMovePacked:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9018FCharacterNetworkMoveDataContainer::ClientFillNetworkMoveData:CharacterMovementComponent.cpp:9609FCharacterNetworkMoveDataContainer::Serialize:CharacterMovementComponent.cpp:9639FCharacterNetworkMoveData::ClientFillNetworkMoveData:CharacterMovementComponent.cpp:9677ServerMovePacked_ClientSend调用:CharacterMovementComponent.cpp:9066ACharacter::ServerMovePacked_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1857UCharacterMovementComponent::ServerMovePacked_ServerReceive:CharacterMovementComponent.cpp:9756
Packed 路径会把 NewMove、PendingMove、OldMove 填入网络 move data container,然后序列化为 bitstream 发给服务器。
Legacy RPC 路径
锚点:
CallServerMove:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9073ACharacter::ServerMove_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1869ACharacter::ServerMoveDual_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1891ACharacter::ServerMoveOld_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1924
Legacy 路径可能发送:
ServerMoveServerMoveNoBaseServerMoveDualServerMoveDualNoBaseServerMoveDualHybridRootMotionServerMoveOld
不要假设“一帧 = 一个 ServerMove RPC”,move combining 和 pending/old move 会改变观察到的包数量。
服务器权威重放与误差校验
Legacy 入口:
UCharacterMovementComponent::ServerMove_Implementation:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9956
主要步骤:
VerifyClientTimeStamp:CharacterMovementComponent.cpp:9978NotifyServerReceivedClientData:CharacterMovementComponent.cpp:9997- 解压 view rotation:
CharacterMovementComponent.cpp:10004 - 计算服务器用于重放的 DeltaTime:
CharacterMovementComponent.cpp:10011 - 更新服务器保存的客户端时间戳:
CharacterMovementComponent.cpp:10013 - 必要时
PC->UpdateRotation(DeltaTime):CharacterMovementComponent.cpp:10037 MoveAutonomous(TimeStamp, DeltaTime, MoveFlags, Accel):CharacterMovementComponent.cpp:10040ServerMoveHandleClientError(...):CharacterMovementComponent.cpp:10047
服务器重放入口:
UCharacterMovementComponent::MoveAutonomous:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10496
MoveAutonomous 会:
UpdateFromCompressedFlags(CompressedFlags):CharacterMovementComponent.cpp:10509CharacterOwner->CheckJumpInput(DeltaTime):CharacterMovementComponent.cpp:10510Acceleration = ConstrainInputAcceleration(NewAccel):CharacterMovementComponent.cpp:10512- clamp 到
GetMaxAcceleration():CharacterMovementComponent.cpp:10513 PerformMovement(DeltaTime):CharacterMovementComponent.cpp:10524
误差处理:
ServerMoveHandleClientError:CharacterMovementComponent.cpp:10051ServerCheckClientError:CharacterMovementComponent.cpp:10367ServerExceedsAllowablePositionError:CharacterMovementComponent.cpp:10412
服务器会比较客户端上报位置、movement mode、base 与服务器重放结果。客户端位置主要用于误差判断,不是直接信任并设置服务器位置。
客户端 Ack、Correction 与重放
RPC 中转入口:
ACharacter::ClientMoveResponsePacked_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1935ACharacter::ClientAckGoodMove_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1947ACharacter::ClientAdjustPosition_Implementation:Engine/Source/Runtime/Engine/Private/Character.cpp:1953
Ack Good Move
入口:
UCharacterMovementComponent::ClientAckGoodMove_Implementation:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:11426
作用:按时间戳确认 saved move,清理已被服务器接受的移动。
Correction
入口:
UCharacterMovementComponent::ClientAdjustPosition_Implementation:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:11052
典型行为:
- 设置服务器位置、速度、base、movement mode。
- 更新 floor / base location / component velocity。
- 设置
ClientData->bUpdatePosition = true。 - 下一次
TickComponent开头进入ClientUpdatePositionAfterServerUpdate。
重放入口:
UCharacterMovementComponent::ClientUpdatePositionAfterServerUpdate:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:8488
重放流程:
- 如果没有 saved moves,无需重放。
- 备份当前 jump/crouch/root motion/analog 状态。
- 设置
CharacterOwner->bClientUpdating = true。 - 遍历
ClientData->SavedMoves:CurrentMove->PrepMoveFor(CharacterOwner)- packed 路径填充 network move data
MoveAutonomous(CurrentMove->TimeStamp, CurrentMove->DeltaTime, CurrentMove->GetCompressedFlags(), CurrentMove->Acceleration)CurrentMove->PostUpdate(... PostUpdate_Replay)
- 恢复备份状态。
- 清理 root motion resimulate 标记。
因此 correction 不是简单“拉回并停止”,而是“拉到服务器确认点,再重放之后玩家已经输入过但尚未确认的 moves”。
SimulatedProxy 与网络平滑
模拟代理路径:
UCharacterMovementComponent::SimulatedTick:Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:1852UCharacterMovementComponent::SimulateMovement:CharacterMovementComponent.cpp:2159UCharacterMovementComponent::SmoothCorrection:CharacterMovementComponent.cpp:8071UCharacterMovementComponent::SmoothClientPosition:CharacterMovementComponent.cpp:8252SmoothClientPosition_Interpolate:CharacterMovementComponent.cpp:8276SmoothClientPosition_UpdateVisuals:CharacterMovementComponent.cpp:8426
其他客户端看到的角色一般不是 AutonomousProxy,而是 SimulatedProxy。它不会消费该玩家的键盘输入,不会跑 saved move 预测,而是接收服务器复制的 transform/velocity/movement mode,并进行平滑。
重要区别:
- correction 时 capsule 可能已经被放到服务器位置。
- mesh 会通过 offset 做视觉平滑。
- 平滑是视觉层,不代表权威碰撞胶囊还留在旧位置。
不同网络角色下的一帧差异
| 场景 | 主要路径 | 特点 |
|---|---|---|
| 单机 / Standalone | ControlledCharacterMove -> PerformMovement -> PhysWalking |
通常无 ServerMove、无 saved move 纠错 |
| Server Authority 本地控制角色 | ControlledCharacterMove -> PerformMovement |
服务器直接权威模拟 |
| Owning Client 自己 | ControlledCharacterMove -> ReplicateMoveToServer -> 本地 PerformMovement -> ServerMove RPC |
本地立即预测,稍后被服务器 ack/correct |
| Server 上的远端玩家 | ServerMove_Implementation -> MoveAutonomous -> PerformMovement |
用客户端输入重放并校验 |
| 其他客户端看到的玩家 | SimulatedTick / SimulateMovement / SmoothCorrection |
不预测输入,靠复制和平滑 |
推荐断点
输入是否进入移动系统
APawn::AddMovementInput:Engine/Source/Runtime/Engine/Private/Pawn.cpp:799APawn::Internal_AddMovementInput:Engine/Source/Runtime/Engine/Private/Pawn.cpp:838APawn::Internal_ConsumeMovementInputVector:Engine/Source/Runtime/Engine/Private/Pawn.cpp:846
观察:
WorldDirectionScaleValueControlInputVectorLastControlInputVector
一帧角色分支
UCharacterMovementComponent::TickComponent:CharacterMovementComponent.cpp:1622ConsumeInputVector:CharacterMovementComponent.cpp:1634ClientUpdatePositionAfterServerUpdate调用点:CharacterMovementComponent.cpp:1714ControlledCharacterMove调用点:CharacterMovementComponent.cpp:1729SimulatedTick调用点:CharacterMovementComponent.cpp:1765
先确认:
CharacterOwner->GetLocalRole()CharacterOwner->GetRemoteRole()IsNetMode(NM_Client)CharacterOwner->IsLocallyControlled()
客户端预测与发送
ReplicateMoveToServer:CharacterMovementComponent.cpp:8789ClientData->UpdateTimeStampAndDeltaTime:CharacterMovementComponent.cpp:8815NewMove->SetMoveFor:CharacterMovementComponent.cpp:8843- move combine:
CharacterMovementComponent.cpp:8850 - 本地预测
PerformMovement:CharacterMovementComponent.cpp:8906 - 保存 move:
CharacterMovementComponent.cpp:8914 - packed RPC:
CharacterMovementComponent.cpp:9018
观察:
NewMove->TimeStampNewMove->DeltaTimeNewMove->AccelerationClientData->PendingMoveClientData->SavedMoves.Num()
Walking 不同步
PhysWalking:CharacterMovementComponent.cpp:5554CalcVelocity调用:CharacterMovementComponent.cpp:5617MoveAlongFloor调用:CharacterMovementComponent.cpp:5645FindFloor调用:CharacterMovementComponent.cpp:5675- ledge 检查:
CharacterMovementComponent.cpp:5679 StartFalling分支:CharacterMovementComponent.cpp:5726AdjustFloorHeight:CharacterMovementComponent.cpp:5731SetBaseFromFloor:CharacterMovementComponent.cpp:5732- 实际位移反推速度:
CharacterMovementComponent.cpp:5772
观察:
VelocityAccelerationCurrentFloorOldFloorMovementBasebJustTeleportedremainingTimeIterations
服务器校验与纠错
ServerMove_Implementation:CharacterMovementComponent.cpp:9956VerifyClientTimeStamp:CharacterMovementComponent.cpp:9978MoveAutonomous:CharacterMovementComponent.cpp:10496ServerMoveHandleClientError:CharacterMovementComponent.cpp:10051ServerCheckClientError:CharacterMovementComponent.cpp:10367
观察:
- 客户端上报
ClientLoc - 服务器模拟后
UpdatedComponent->GetComponentLocation() ClientMovementModeMovementBaseDeltaTime
客户端纠错重放和平滑
ClientAdjustPosition_Implementation:CharacterMovementComponent.cpp:11052ClientUpdatePositionAfterServerUpdate:CharacterMovementComponent.cpp:8488SmoothCorrection:CharacterMovementComponent.cpp:8071SmoothClientPosition_Interpolate:CharacterMovementComponent.cpp:8276
观察:
ClientData->bUpdatePositionClientData->SavedMovesMeshTranslationOffset- capsule 位置与 mesh 视觉位置差异
调试日志与控制台变量
常用日志类别:
LogNetPlayerMovement:网络移动、ServerMove、纠错相关。LogCharacterMovement:角色移动常规日志。LogCharacterNetSmoothing:网络平滑相关。
常用 CVar:
p.NetShowCorrections:显示网络纠错,定义在CharacterMovementComponent.cpp:411p.NetCorrectionLifetime:纠错显示持续时间,定义在CharacterMovementComponent.cpp:419p.NetForceClientServerMoveLossPercent:模拟 ServerMove 丢包,定义在CharacterMovementComponent.cpp:441p.NetForceClientServerMoveLossDuration:模拟丢包持续时间,定义在CharacterMovementComponent.cpp:450
常见误区
-
误以为
AddMovementInput会立即移动
实际只是累积ControlInputVector,移动发生在 CMC tick。 -
Tick 后还看
ControlInputVector
它在ConsumeInputVector后被清零,应看LastControlInputVector、Acceleration或 saved move。 -
误以为客户端等待服务器才移动
owning client 会本地预测,服务器只是稍后确认或纠错。 -
误以为 ServerMove 直接采用客户端位置
客户端位置用于误差比较;服务器会用输入和 flags 重放。 -
忽略 move combining
网络上不一定一帧一个 ServerMove,可能 pending、dual、old move 合包。 -
只看 Velocity,不看 Floor/Base
Walking 的分歧经常来自 floor trace、台阶、ledge、base-relative location,而不是简单速度公式。 -
混淆 capsule correction 和 mesh smoothing
capsule 可被直接校正到服务器位置,mesh 再平滑追上;视觉平滑不等于物理胶囊仍在旧位置。 -
忽略 Root Motion / Custom Movement 的 saved move 扩展
如果自定义移动只改客户端变量,没有写入 compressed flags、saved move 或 network move data,服务器重放会不同步。
关键源码锚点表
| 主题 | 源码位置 |
|---|---|
APawn::AddMovementInput |
Engine/Source/Runtime/Engine/Private/Pawn.cpp:799 |
APawn::Internal_AddMovementInput |
Engine/Source/Runtime/Engine/Private/Pawn.cpp:838 |
APawn::Internal_ConsumeMovementInputVector |
Engine/Source/Runtime/Engine/Private/Pawn.cpp:846 |
UPawnMovementComponent::AddInputVector |
Engine/Source/Runtime/Engine/Private/Components/PawnMovementComponent.cpp:64 |
UPawnMovementComponent::ConsumeInputVector |
Engine/Source/Runtime/Engine/Private/Components/PawnMovementComponent.cpp:82 |
UCharacterMovementComponent::TickComponent |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:1622 |
SimulatedTick |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:1852 |
SimulateMovement |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:2159 |
PerformMovement |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:2703 |
StartNewPhysics |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:3454 |
CalcVelocity |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:3786 |
ComputeGroundMovementDelta |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:5394 |
MoveAlongFloor |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:5457 |
MaintainHorizontalGroundVelocity |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:5536 |
PhysWalking |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:5554 |
AdjustFloorHeight |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:6194 |
FindFloor |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:7100 |
StepUp |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:7450 |
SmoothCorrection |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:8071 |
SmoothClientPosition |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:8252 |
ClientUpdatePositionAfterServerUpdate |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:8488 |
ReplicateMoveToServer |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:8789 |
CallServerMovePacked |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9018 |
FCharacterNetworkMoveDataContainer::ClientFillNetworkMoveData |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9609 |
FCharacterNetworkMoveDataContainer::Serialize |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9639 |
FCharacterNetworkMoveData::ClientFillNetworkMoveData |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9677 |
ServerMovePacked_ServerReceive |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9756 |
ServerMove_Implementation |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:9956 |
ServerMoveHandleClientError |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10051 |
ServerCheckClientError |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10367 |
ServerExceedsAllowablePositionError |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10412 |
MoveAutonomous |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10496 |
ClientAdjustPosition_Implementation |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:11052 |
ClientAckGoodMove_Implementation |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:11426 |
FSavedMove_Character::SetMoveFor |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:12502 |
FSavedMove_Character::CanCombineWith |
Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:12823 |
ACharacter::ServerMovePacked_Implementation |
Engine/Source/Runtime/Engine/Private/Character.cpp:1857 |
ACharacter::ServerMove_Implementation |
Engine/Source/Runtime/Engine/Private/Character.cpp:1869 |
ACharacter::ClientMoveResponsePacked_Implementation |
Engine/Source/Runtime/Engine/Private/Character.cpp:1935 |
ACharacter::ClientAckGoodMove_Implementation |
Engine/Source/Runtime/Engine/Private/Character.cpp:1947 |
ACharacter::ClientAdjustPosition_Implementation |
Engine/Source/Runtime/Engine/Private/Character.cpp:1953 |
FSavedMove_Character |
Engine/Source/Runtime/Engine/Classes/GameFramework/CharacterMovementComponent.h:2912 |
FNetworkPredictionData_Client_Character |
Engine/Source/Runtime/Engine/Classes/GameFramework/CharacterMovementComponent.h:3080 |
FNetworkPredictionData_Server_Character |
Engine/Source/Runtime/Engine/Classes/GameFramework/CharacterMovementComponent.h:3204 |
简化调用链图
键盘 / 输入系统-> 项目移动函数-> APawn::AddMovementInput-> UPawnMovementComponent::AddInputVector-> APawn::Internal_AddMovementInput-> ControlInputVector += InputUCharacterMovementComponent::TickComponent-> ConsumeInputVector-> if AutonomousProxy client and has correction:ClientUpdatePositionAfterServerUpdate-> replay SavedMoves with MoveAutonomous-> ControlledCharacterMove-> CheckJumpInput-> InputVector -> Acceleration-> Authority: PerformMovement-> AutonomousProxy client: ReplicateMoveToServer-> Create FSavedMove-> SetMoveFor-> optional combine PendingMove-> PerformMovement locally-> StartNewPhysics-> PhysWalking-> SavedMoves.Push-> CallServerMovePacked / CallServerMoveServer receives ServerMove-> ServerMovePacked_ServerReceive or ServerMove_Implementation-> VerifyClientTimeStamp-> GetServerMoveDeltaTime-> MoveAutonomous-> compressed flags -> movement state-> NewAccel -> Acceleration-> PerformMovement-> StartNewPhysics-> PhysWalking-> ServerMoveHandleClientError-> ack or correctionClient receives response-> ClientAckGoodMove: drop acked saved moves-> ClientAdjustPosition: set server location/velocity/mode/base, mark bUpdatePosition-> next Tick: ClientUpdatePositionAfterServerUpdate replays unacked SavedMovesOther clients-> SimulatedTick / SimulateMovement-> SmoothCorrection / SmoothClientPosition
