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 质量门审查。
This commit is contained in:
@@ -0,0 +1,382 @@
|
||||
# 角色控制技术设计文档(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 参数
|
||||
|
||||
```cpp
|
||||
// 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
|
||||
|
||||
```cpp
|
||||
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 控制。
|
||||
|
||||
```cpp
|
||||
// InputYawScale 在 PlayerController 中设置
|
||||
// 灵敏度通过 IA 的 Scale 值控制,不需要自定义旋转速度限制
|
||||
// UE5 鼠标输入是相对移动,不受固定 °/s 限制
|
||||
// v0.1 使用默认鼠标输入灵敏度,后续版本可加灵敏度滑块
|
||||
```
|
||||
|
||||
**垂直限幅实现**:在 CameraManager 中设置
|
||||
|
||||
```cpp
|
||||
// AChildHoodPlayerController::BeginPlay 或构造函数中
|
||||
PlayerCameraManager->ViewPitchMin = -30.0f; // 向下看最多 30°
|
||||
PlayerCameraManager->ViewPitchMax = 45.0f; // 向上看最多 45°
|
||||
```
|
||||
|
||||
> 注:执行案中 150°/s 是手柄摇杆的设计参考值。键鼠模式下鼠标移动是相对输入,由玩家手速决定实际旋转速度。v0.1 优先键鼠,此参数暂不在代码中硬性限制。
|
||||
|
||||
**可调参数**:ViewPitchMin, ViewPitchMax, IA Scale
|
||||
|
||||
---
|
||||
|
||||
#### C4. 摄像机碰撞处理
|
||||
|
||||
**实现**:启用 SpringArm 原生碰撞检测
|
||||
|
||||
```cpp
|
||||
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. 跑动中角色始终背对摄像机
|
||||
|
||||
**实现**:已有配置满足
|
||||
|
||||
```cpp
|
||||
bUseControllerRotationYaw = false; // 角色不跟随 Controller Yaw
|
||||
GetCharacterMovement()->bOrientRotationToMovement = true; // 角色朝移动方向旋转
|
||||
GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f); // 转向速度 720°/s
|
||||
```
|
||||
|
||||
角色转向速度 720°/s 远快于鼠标旋转速度,自然满足"摄像机追不到角色正面"的效果。无需额外逻辑。
|
||||
|
||||
---
|
||||
|
||||
### 二、移动系统
|
||||
|
||||
#### M1. 移动方向(相对摄像机,对角 45° 合成)
|
||||
|
||||
**实现**:已有 `DoMove()` 逻辑满足
|
||||
|
||||
```cpp
|
||||
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 参数配置
|
||||
|
||||
```cpp
|
||||
GetCharacterMovement()->bOrientRotationToMovement = true;
|
||||
GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f);
|
||||
```
|
||||
|
||||
CMC 默认走最短路径旋转,转向期间角色持续移动(不"停顿再转向")。**无需修改。**
|
||||
|
||||
---
|
||||
|
||||
#### M3. 跑步(4.5 m/s,起步加速 0.2s)
|
||||
|
||||
**速度**:
|
||||
```cpp
|
||||
GetCharacterMovement()->MaxWalkSpeed = 450.0f; // 4.5 m/s (UE5 1uu = 1cm)
|
||||
```
|
||||
|
||||
**加速**:CMC 的 `MaxAcceleration` 控制加速过程
|
||||
|
||||
```cpp
|
||||
// 从 0 到 450 cm/s 在 0.2s → 加速度 = 450/0.2 = 2250 cm/s²
|
||||
GetCharacterMovement()->MaxAcceleration = 2250.0f;
|
||||
```
|
||||
|
||||
> 注:CMC 加速不是严格线性,受 GroundFriction 等因素影响。2250 是起始值,实际手感需测试微调。
|
||||
|
||||
---
|
||||
|
||||
#### M4. 停止减速(0.3s)
|
||||
|
||||
**实现**:
|
||||
|
||||
```cpp
|
||||
// 从 450 到 0 cm/s 在 0.3s → 减速度 = 450/0.3 = 1500 cm/s²
|
||||
GetCharacterMovement()->BrakingDecelerationWalking = 1500.0f;
|
||||
```
|
||||
|
||||
> 同样受 GroundFriction 影响,1500 是起始值。
|
||||
|
||||
---
|
||||
|
||||
#### M5. 坡道与台阶(坡度 ≤45°,台阶 ≤0.15m)
|
||||
|
||||
**实现**:
|
||||
|
||||
```cpp
|
||||
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 指针和绑定
|
||||
|
||||
```cpp
|
||||
// 新增成员(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 及其绑定
|
||||
|
||||
```cpp
|
||||
// 删除 JumpAction 成员
|
||||
// 删除 SetupPlayerInputComponent 中的 Jump 绑定
|
||||
// 删除 DoJumpStart/DoJumpEnd 函数
|
||||
// CMC: GetCharacterMovement()->JumpZVelocity 不需要设置(不跳跃)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 四、输入优先级 & 跨系统交互
|
||||
|
||||
#### P1. 交互中忽略移动输入
|
||||
|
||||
**实现**:在 `DoMove()` 中添加状态检查
|
||||
|
||||
```cpp
|
||||
// 新增成员
|
||||
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. 状态信号提供
|
||||
|
||||
**实现**:提供查询接口
|
||||
|
||||
```cpp
|
||||
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 | 构造函数 |
|
||||
Reference in New Issue
Block a user