Files
ChildHood/docs/technical/player-controller-tech.md
T
starmen1265 150f94c674 docs(technical): v0.1 程序设计——角色控制+交互+收集三份技术方案
P-003 步骤④程序设计产出:

- player-controller-tech.md: 角色控制系统(参数调整+输入绑定,2-3天)
- interaction-system-tech.md: 交互系统核心框架(状态机+推镜+物品中转,5-7天)
- collection-system-tech.md: 收集系统进度追踪+通知UI(1-2天)

覆盖三份执行案全部行为规则,含美术需求清单和技术风险分析。
等待 PM 质量门审查。
2026-06-06 00:30:50 +08:00

12 KiB
Raw Blame History

角色控制技术设计文档(v0.1 原型)

任务ID: P-003(部分) 对应执行案: docs/design/prototype/player-controller-execution.md 阶段: 原型 日期: 2026-06-06


概述

角色控制系统基于现有 AChildHoodCharacter + AChildHoodPlayerController 框架进行参数调整和少量代码修改。核心架构(SpringArm 摄像机 + Enhanced Input + CMC 移动)已就绪,v0.1 工作以配置级调整为主,不引入新的类或组件。

实现复杂度:低 预估工期:2-3 天 新增/修改代码量:约 80-100 行 C++


类与组件架构

修改现有类

类 修改内容 代码量
AChildHoodCharacter 移除跳跃、调整 CMC/SpringArm 参数、添加交互状态标志、新增交互相关 IA 绑定 ~60 行
AChildHoodPlayerController 调整 Pitch 限幅(通过 CameraManager) ~5 行

不新增类

v0.1 角色控制系统不引入新类。所有功能通过修改现有类的参数和少量逻辑实现。

组件挂载关系(不变)

AChildHoodCharacter
├── UCapsuleComponent (Root) — 碰撞胶囊体
├── USkeletalMeshComponent (Mesh) — 角色网格
├── USpringArmComponent (CameraBoom) — 摄像机摇臂
└── UCameraComponent (FollowCamera) — 跟随摄像机

AChildHoodPlayerController
├── APlayerCameraManager — 摄像机管理器(设置 Pitch 限幅)
└── UEnhancedInputComponent — 输入组件
    └── IMC 注册(通过 DefaultMappingContexts)

行为规则 → 实现方案映射

一、摄像机系统

C1. 默认位置(距离 3.5m / 高度 0.8m / 俯角 15°)

实现:构造函数中配置 SpringArm 参数

// AChildHoodCharacter 构造函数
CameraBoom->TargetArmLength = 350.0f;           // 3.5m 距离
CameraBoom->SocketOffset = FVector(0.f, 0.f, 80.f); // 0.8m 高于角色
// 初始俯角由 Controller Pitch 控制,在 PlayerController 中设置初始旋转

可调参数:TargetArmLength, SocketOffset.Z


C2. 软跟随(3-5x 角色移动速度)

实现:启用 SpringArm 原生 Camera Lag

CameraBoom->bEnableCameraLag = true;
CameraBoom->CameraLagSpeed = 6.0f;  // 可调,范围 2-8
CameraBoom->bEnableCameraRotationLag = false; // v0.1 不启用旋转延迟

可调参数:CameraLagSpeed


C3. 视角旋转(水平 150°/s,垂直 +45°/-30°)

水平旋转实现:通过 Enhanced Input IA 的 Value 值 × PlayerController::InputYawScale 控制。

// InputYawScale 在 PlayerController 中设置
// 灵敏度通过 IA 的 Scale 值控制,不需要自定义旋转速度限制
// UE5 鼠标输入是相对移动,不受固定 °/s 限制
// v0.1 使用默认鼠标输入灵敏度,后续版本可加灵敏度滑块

垂直限幅实现:在 CameraManager 中设置

// AChildHoodPlayerController::BeginPlay 或构造函数中
PlayerCameraManager->ViewPitchMin = -30.0f;  // 向下看最多 30°
PlayerCameraManager->ViewPitchMax = 45.0f;   // 向上看最多 45°

注:执行案中 150°/s 是手柄摇杆的设计参考值。键鼠模式下鼠标移动是相对输入,由玩家手速决定实际旋转速度。v0.1 优先键鼠,此参数暂不在代码中硬性限制。

可调参数:ViewPitchMin, ViewPitchMax, IA Scale


C4. 摄像机碰撞处理

实现:启用 SpringArm 原生碰撞检测

CameraBoom->bDoCollisionTest = true;
CameraBoom->ProbeSize = 12.0f;   // 碰撞探针半径
CameraBoom->ProbeChannel = ECC_Camera; // 使用 Camera 碰撞通道

// 最小距离保证:SpringArm 自动缩短到碰撞面
// 当目标位置被阻挡时,SpringArm 将摄像机移到最近的未阻挡位置
// 默认行为已满足"紧贴碰撞面内侧"的要求

最小距离保证(0.5m):SpringArm 的 TargetArmLength 最短会被碰撞面推到约 0(取决于探针半径和角色胶囊体大小)。如需严格保证 0.5m 最小距离,可在蓝图中加 Tick 检查后处理。v0.1 先用原生行为,视体验再决定是否添加。

恢复:碰撞消除后 SpringArm 自动恢复到 TargetArmLength,配合 Camera Lag 实现平滑回位。

v0.1 简化:仅处理与静态几何体碰撞(默认行为),不处理动态物体。


C5. 跑动中角色始终背对摄像机

实现:已有配置满足

bUseControllerRotationYaw = false;          // 角色不跟随 Controller Yaw
GetCharacterMovement()->bOrientRotationToMovement = true; // 角色朝移动方向旋转
GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f); // 转向速度 720°/s

角色转向速度 720°/s 远快于鼠标旋转速度,自然满足"摄像机追不到角色正面"的效果。无需额外逻辑。


二、移动系统

M1. 移动方向(相对摄像机,对角 45° 合成)

实现:已有 DoMove() 逻辑满足

void AChildHoodCharacter::DoMove(float Right, float Forward)
{
    const FRotator Rotation = GetController()->GetControlRotation();
    const FRotator YawRotation(0, Rotation.Yaw, 0);
    const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
    const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
    AddMovementInput(ForwardDirection, Forward);
    AddMovementInput(RightDirection, Right);
}
  • 对角输入(W+A)由 Enhanced Input 的 2D Axis 自然处理
  • AddMovementInput 不叠加速度(CMC 内部归一化)
  • 连续旋转中移动方向实时跟随摄像机朝向(每帧重新计算方向)

无需修改。


M2. 角色转向(720°/s,最短路径,边跑边转)

实现:CMC 参数配置

GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f);

CMC 默认走最短路径旋转,转向期间角色持续移动(不"停顿再转向")。无需修改。


M3. 跑步(4.5 m/s,起步加速 0.2s)

速度:

GetCharacterMovement()->MaxWalkSpeed = 450.0f; // 4.5 m/s (UE5 1uu = 1cm)

加速:CMC 的 MaxAcceleration 控制加速过程

// 从 0 到 450 cm/s 在 0.2s → 加速度 = 450/0.2 = 2250 cm/s²
GetCharacterMovement()->MaxAcceleration = 2250.0f;

注:CMC 加速不是严格线性,受 GroundFriction 等因素影响。2250 是起始值,实际手感需测试微调。


M4. 停止减速(0.3s)

实现:

// 从 450 到 0 cm/s 在 0.3s → 减速度 = 450/0.3 = 1500 cm/s²
GetCharacterMovement()->BrakingDecelerationWalking = 1500.0f;

同样受 GroundFriction 影响,1500 是起始值。


M5. 坡道与台阶(坡度 ≤45°,台阶 ≤0.15m)

实现:

GetCharacterMovement()->WalkableFloorAngle = 45.0f;    // 最大可行走坡度
// 台阶高度由胶囊体半径和 CMC 的 StepHeight 决定
// 默认 StepOffset = 45.0f (4.5cm),覆盖 0.15m 需要调大
// 但 v0.1 场景设计避免高台阶,先保持默认
GetCharacterMovement()->SetWalkableFloorAngle(45.0f);

三、输入映射

I1. WASD/方向键 → 移动

实现:已有 IA_Move + IMC 配置。保持不变。

I2. 鼠标移动 → 视角旋转

实现:已有 IA_MouseLook + IMC 配置。保持不变。

I3. E/ESC/Tab/滚轮 → 委托交互系统

实现:在 Character 中添加交互相关 IA 指针和绑定

// 新增成员(AChildHoodCharacter.h)
UPROPERTY(EditAnywhere, Category="Input")
UInputAction* InteractAction;     // E 键

UPROPERTY(EditAnywhere, Category="Input")
UInputAction* CancelAction;       // ESC 键

UPROPERTY(EditAnywhere, Category="Input")
UInputAction* SwitchInteractAction; // Tab 键

// SetupPlayerInputComponent 中绑定
// 回调函数直接调用 InteractionManager 的对应接口

具体回调实现见交互系统技术设计文档。

I4. 移除跳跃

实现:移除 JumpAction 及其绑定

// 删除 JumpAction 成员
// 删除 SetupPlayerInputComponent 中的 Jump 绑定
// 删除 DoJumpStart/DoJumpEnd 函数
// CMC: GetCharacterMovement()->JumpZVelocity 不需要设置(不跳跃)

四、输入优先级 & 跨系统交互

P1. 交互中忽略移动输入

实现:在 DoMove() 中添加状态检查

// 新增成员
bool bIsInteracting = false;

// 修改 DoMove
void AChildHoodCharacter::DoMove(float Right, float Forward)
{
    if (bIsInteracting) return; // 交互中忽略移动
    // ... 原有逻辑
}

// 外部接口(供 InteractionManager 调用)
UFUNCTION(BlueprintCallable)
void SetInteracting(bool bInteracting);

P2. 交互中摄像机控制权交接

实现:InteractionManager 在进入交互时通过 SetViewTargetWithBlend 切换摄像机目标;退出时切换回 Character。角色控制系统本身不需要修改摄像机逻辑。

交互结束后摄像机自动回到 SpringArm 默认跟随(因为 ViewTarget 切回 Character,SpringArm 恢复控制)。

P3. 状态信号提供

实现:提供查询接口

UFUNCTION(BlueprintCallable, BlueprintPure)
bool IsInteracting() const { return bIsInteracting; }

UFUNCTION(BlueprintCallable, BlueprintPure)
bool IsRunning() const;
// IsRunning: GetVelocity().Size() > Threshold && GetCharacterMovement()->IsMovingOnGround()

数据流

配置参数流

C++ 构造函数默认值 → 蓝图派生类可覆盖 → 运行时通过 Details 面板微调

v0.1 原型阶段所有参数在 C++ 中设置默认值,蓝图可覆盖。不使用 DataAsset 或配置表。 批量生产阶段迁移到参数 DataAsset。

运行时状态流

Enhanced Input (WASD/鼠标)
    → AChildHoodPlayerController (IMC 注册)
    → AChildHoodCharacter (IA 回调)
        ├─ DoMove() → CMC (AddMovementInput)
        ├─ DoLook() → Controller (AddYawInput/AddPitchInput)
        │                → SpringArm (Controller Rotation)
        │                    → Camera (位置/旋转)
        ├─ InteractAction → InteractionManager (委托)
        └─ bIsInteracting → DoMove() (输入屏蔽)

美术资源需求

v0.1 角色控制系统不直接需要美术资产。以下为间接需求:

资源类型 名称 数量 规格 说明
占位动画 Idle(站立待机) 1 简单 T-pose 或 A-pose 即可 v0.1 可无动画
占位动画 Run(跑步循环) 1 简单跑步循环,角色可在地面滑动 执行案明确说"若无动画资源,角色在地面滑动也可接受"

v0.1 角色控制不包含跳跃、蹲下、攀爬,因此不需要对应动画。


技术风险与注意事项

风险 等级 说明 缓解措施
软跟随手感不佳 🟢 低 CameraLagSpeed 需要实际测试调整 多个预设值快速切换测试
摄像机碰撞穿墙 🟢 低 SpringArm 原生碰撞处理基本满足 角落/窄空间需额外测试
CMC 加速/减速不符合预期 🟢 低 CMC 物理模型不完全线性 参数范围已预留,微调即可
角色转身"飘"的感觉 🟢 低 720°/s 偏快可能导致动画不自然 v0.1 无正式动画,暂时不是问题

可调参数汇总

所有参数均在构造函数中设置默认值,蓝图可覆盖:

参数 C++ 属性 默认值 位置
摄像机距离 CameraBoom->TargetArmLength 350.0f 构造函数
摄像机高度 CameraBoom->SocketOffset.Z 80.0f 构造函数
跟随速度 CameraBoom->CameraLagSpeed 6.0f 构造函数
俯角上限 CameraManager->ViewPitchMax 45.0f BeginPlay
俯角下限 CameraManager->ViewPitchMin -30.0f BeginPlay
碰撞检测 CameraBoom->bDoCollisionTest true 构造函数
跑步速度 CMC->MaxWalkSpeed 450.0f 构造函数
加速度 CMC->MaxAcceleration 2250.0f 构造函数
减速度 CMC->BrakingDecelerationWalking 1500.0f 构造函数
转向速度 CMC->RotationRate.Yaw 720.0f 构造函数
可行走坡度 CMC->WalkableFloorAngle 45.0f 构造函数