输入控制与视角层级结构
1. 输入是如何控制Pawn和Camera的
Rotation部分: 所有的输入首先会通过AddPitch/Yaw/RollInput修改RotationInput。
RotationInput记录了每帧的输入变化。在PlayerController TickActor->PlayerTick->UpdateRotaton 中通过
PlayerCameraManager->ProcessViewRotation(DeltaTime, ViewRotation, DeltaRot);
累加给ViewRotation,之后赋值给ControlRotation。当帧会清0
修改ControlRotation。各个地方从ControlRotation中获取自己的信息。在给之前会先通过PlayerCameraManager对Rotation进行限制(例如Pitch)。
- Pawn的Rotation: 在Controller的
UpdateRotation调用时,通过调用Pawn的FaceRotation函数进行更新。内部通过bUseControllerRotationPitch/Yaw/Roll参数,来指定获取ControlRotation的一部分或全部。- 第一人称视角(FPP) 通常只获取Yaw,这样Pawn的Yaw会和输入保持同步。
- 移动输入影响ControlInputVector(在Pawn上),通过APawn::AddMovementInput
- UCharacterMovementComponent::TickComponent开头通过ConsumeInputVector,清空并返回ControlInputVector
- 返回值会作为Scale缩放最大加速度来得到Acceleration,发生在UCharacterMovementComponent::ControlledCharacterMove,这里也触发JumpInput(但不改变加速度,直接修改Velocity.Z)。
- 如果是联机的客户端,该函数会调用ReplicateMoveToServer(DeltaSeconds, Acceleration);内部调用PerformMovement移动。
蹲下输入1p和DS在Movement执行前执行UCharacterMovementComponent::UpdateCharacterStateBeforeMovement。3p通过Rep函数触发。
2. FPP视角下,Camera和FPP Mesh的层级结构
将SpringArm挂在Capsule上,并调整到预期的Camera位置。将FPP Mesh挂在SpringArm上,将其Root与TPP mesh的Root对齐。将Camera挂在FPP Mesh的CameraBone上。
原因:
- Camera需要挂在FPP Mesh的
CameraBone上,方便Camera动画制作。这样,Camera的旋转由FPP Mesh决定。这就要求输入(即ControlRotation)能够旋转FPP Mesh。 - FPP Mesh通常具备完整的人形骨骼,其
Root点也位于双脚中间。直接旋转FPP Mesh会导致绕Root旋转。我们希望看起来是Camera在原地旋转(实际上Camera也有自身的晃动,所以不能让Camera带着Mesh转)。 - 因此,增加一个中间层级——目前是使用
SpringArm。将SpringArm和Camera对齐。旋转SpringArm时,FPP Mesh和Camera保持相对不变,从而实现Camera带着Mesh转的效果。
Camera 的Transform会通过RPC:ServerUpdateCamera 发送给Server,需要在PlayerCameraManager上勾选bUseClientSideCameraUpdates
思考题
如果没有SpringArm,如何通过调整FPP原点的Transform,达到上述Camera原地旋转的效果?
分析:
需要找出Camera的Transform和FPP原点的Transform之间的关系。由于上述层级结构,Camera的世界变换记为,相对于FPP原点的变换记为,FPP原点的世界变换记为,则有:
即:
只需根据需求设置好,再利用上述公式计算出即可。
延伸问题:
类似的问题很多,已知子节点的目标变换,但希望通过调整某个父节点的变换来实现。
设最终父节点的世界变换为,目标子节点的世界变换为,相对世界变换为,中间父节点相对变换为、等(假设有两层)。
首先正向思考:
将中间层级的相对变换记为,则:
对Camera的Transform依赖导致跟不上Camera
比如枪上的激光,要命中准心位置,需要知道Camera的朝向做Trace来得知。
CameraManager的更新在 Post Physics 之后,Post UpdateWork 之前。提前获取的Camera位置可能不准确,可以在Post UpdateWork阶段进行纠正