docs(review): P-008交互系统程序设计质量门审查通过+美术调研+工作流完善
- P-008 交互系统技术设计审查通过,审查记录 docs/plans/reviews/P-008-review.md - D-001 关卡执行案审查通过,审查记录 docs/plans/reviews/D-001-review.md - 新增 AI 美术调研参考图(我的暑假/放学后少年/真实场景/美术风格) - 新增关卡执行案、白模搭建指南和搭建报告 - 完善工作流技能:质量门审查、Agent记忆、需求分析 - 更新交互系统和角色控制系统技术设计文档 - 清理过时参考文档
This commit is contained in:
@@ -1,53 +1,241 @@
|
||||
# 角色控制技术设计文档(v0.1 原型)
|
||||
|
||||
> 任务ID: P-003(部分)
|
||||
> 任务ID: P-007
|
||||
> 对应执行案: `docs/design/prototype/player-controller-execution.md`
|
||||
> 关联系统: 交互系统(输入互斥 + 摄像机控制权交接)、场景系统(碰撞体 + 出生点)
|
||||
> 阶段: 原型
|
||||
> 日期: 2026-06-06
|
||||
> 日期: 2026-06-07
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
角色控制系统基于现有 `AChildHoodCharacter` + `AChildHoodPlayerController` 框架进行参数调整和少量代码修改。核心架构(SpringArm 摄像机 + Enhanced Input + CMC 移动)已就绪,v0.1 工作以**配置级调整**为主,不引入新的类或组件。
|
||||
角色控制系统基于现有 `AChildHoodCharacter` + `AChildHoodPlayerController` 框架进行参数调整和少量代码修改。核心架构(SpringArm 摄像机 + Enhanced Input + CMC 移动)已就绪,v0.1 工作以**配置级调整**为主,不引入新的类或组件。同时需要移除跳跃逻辑、添加交互状态标志及交互相关 IA 绑定。
|
||||
|
||||
**实现复杂度**:低
|
||||
**预估工期**:2-3 天
|
||||
**新增/修改代码量**:约 80-100 行 C++
|
||||
**预估工期**:1-2 天
|
||||
**新增/修改代码量**:约 60-80 行 C++(净增约 30 行,删除约 20 行)
|
||||
|
||||
---
|
||||
|
||||
## 类与组件架构
|
||||
## 1. 需求功能点罗列
|
||||
|
||||
### 修改现有类
|
||||
从执行文档中提取每条行为规则,按实现方式分类。
|
||||
|
||||
| 类 | 修改内容 | 代码量 |
|
||||
|----|---------|--------|
|
||||
| `AChildHoodCharacter` | 移除跳跃、调整 CMC/SpringArm 参数、添加交互状态标志、新增交互相关 IA 绑定 | ~60 行 |
|
||||
| `AChildHoodPlayerController` | 调整 Pitch 限幅(通过 CameraManager) | ~5 行 |
|
||||
### UE 内置功能
|
||||
|
||||
### 不新增类
|
||||
以下功能点直接使用 UE5 引擎内置能力,无需或仅需极少量自定义代码:
|
||||
|
||||
v0.1 角色控制系统不引入新类。所有功能通过修改现有类的参数和少量逻辑实现。
|
||||
| 功能点 | 使用的 UE 内置能力 | 对应行为规则 | 备注 |
|
||||
|--------|-------------------|-------------|------|
|
||||
| 摄像机默认位置(3.5m / 0.8m / 15° 俯角) | SpringArm `TargetArmLength` + `SocketOffset` | C1 默认位置 | 构造函数配置 |
|
||||
| 摄像机软跟随(3-5x 角色速度) | SpringArm `CameraLag` + `CameraLagSpeed` | C2 跟随规则 | 构造函数启用 |
|
||||
| 视角水平旋转(150°/s) | Enhanced Input IA + `AddControllerYawInput` | C3 视角旋转 | 键鼠为相对输入,不硬限 °/s |
|
||||
| 视角垂直限幅(+45°/-30°) | `PlayerCameraManager::ViewPitchMin/Max` | C3 视角旋转 | BeginPlay 中设置 |
|
||||
| 摄像机碰撞处理 | SpringArm `bDoCollisionTest` + `ProbeSize` | C4 碰撞处理 | 构造函数启用 |
|
||||
| 跑动中角色背对摄像机 | CMC `bOrientRotationToMovement` + `RotationRate` | C5 跑动背对 | 转向速度 720°/s 远快于鼠标 |
|
||||
| 移动方向相对摄像机(含对角 45°) | Enhanced Input 2D Axis + `AddMovementInput` | M1 移动方向 | 已有 `DoMove()` 满足 |
|
||||
| 角色转向(720°/s,最短路径) | CMC `RotationRate` + 默认最短路径旋转 | M2 角色转向 | 无需修改 |
|
||||
| 跑步速度(4.5 m/s) | CMC `MaxWalkSpeed` | M3 跑步 | 构造函数设置 |
|
||||
| 起步加速(0.2s) | CMC `MaxAcceleration` | M3 跑步 | 450/0.2 = 2250 cm/s² |
|
||||
| 停止减速(0.3s) | CMC `BrakingDecelerationWalking` | M4 停止减速 | 450/0.3 = 1500 cm/s² |
|
||||
| 坡道可行走(≤45°) | CMC `WalkableFloorAngle` | M5 坡道与台阶 | 构造函数设置 |
|
||||
| WASD/方向键移动输入 | Enhanced Input IMC/IA(已有) | I1 移动输入 | 无修改 |
|
||||
| 鼠标视角旋转输入 | Enhanced Input IMC/IA(已有) | I2 视角输入 | 无修改 |
|
||||
|
||||
### 组件挂载关系(不变)
|
||||
### 自定义实现
|
||||
|
||||
以下功能点需要编写自定义 C++ / 蓝图代码:
|
||||
|
||||
| 功能点 | 实现方式概述 | 对应行为规则 | 预估复杂度 |
|
||||
|--------|-------------|-------------|-----------|
|
||||
| 移除跳跃 | 删除 `JumpAction` 成员、`DoJumpStart/End` 函数、Input 绑定 | I4 移除跳跃 | 低 |
|
||||
| 交互中忽略移动输入 | `bIsInteracting` 标志 + `DoMove()` 前置检查 | P1 交互中屏蔽移动 | 低 |
|
||||
| 交互相关 IA 绑定 | 新增 `InteractAction`/`CancelAction`/`SwitchInteractAction` 成员 | I3 交互输入 | 低 |
|
||||
| 交互状态接口 | `SetInteracting()`/`IsInteracting()`/`IsRunning()` 方法 | P3 状态信号 | 低 |
|
||||
| 摄像机控制权交接 | 提供 `FollowCamera` 访问器,交互系统通过 `SetViewTargetWithBlend` 切换 | P2 摄像机控制权 | 低(接口方) |
|
||||
|
||||
> **分类原则**:角色控制系统 90% 需求由 UE 内置能力覆盖,仅交互协调相关逻辑需要自定义。无复杂状态机或自定义算法。
|
||||
|
||||
---
|
||||
|
||||
## 2. 功能领域图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph 输入层
|
||||
Input[输入处理模块<br/>Enhanced Input 回调]
|
||||
end
|
||||
|
||||
subgraph 核心层
|
||||
Movement[移动控制模块<br/>CMC 参数配置]
|
||||
Camera[摄像机模块<br/>SpringArm 参数配置]
|
||||
CharState[角色状态模块<br/>交互标志 + 查询接口]
|
||||
end
|
||||
|
||||
subgraph 外部系统
|
||||
Interaction[交互系统<br/>读/写角色状态]
|
||||
end
|
||||
|
||||
Input -->|WASD/鼠标| Movement
|
||||
Input -->|鼠标| Camera
|
||||
Input -->|E/ESC/Tab| Interaction
|
||||
Movement -->|bIsInteracting 检查| CharState
|
||||
Interaction -->|SetInteracting| CharState
|
||||
Interaction -->|SetViewTargetWithBlend| Camera
|
||||
CharState -.->|IsInteracting/IsRunning| Interaction
|
||||
```
|
||||
AChildHoodCharacter
|
||||
├── UCapsuleComponent (Root) — 碰撞胶囊体
|
||||
├── USkeletalMeshComponent (Mesh) — 角色网格
|
||||
├── USpringArmComponent (CameraBoom) — 摄像机摇臂
|
||||
└── UCameraComponent (FollowCamera) — 跟随摄像机
|
||||
|
||||
AChildHoodPlayerController
|
||||
├── APlayerCameraManager — 摄像机管理器(设置 Pitch 限幅)
|
||||
└── UEnhancedInputComponent — 输入组件
|
||||
└── IMC 注册(通过 DefaultMappingContexts)
|
||||
### 模块职责说明
|
||||
|
||||
| 模块 | 职责 | 关键输入 | 关键输出 |
|
||||
|------|------|---------|---------|
|
||||
| 输入处理模块 | 接收 Enhanced Input 回调,分发到移动/视角/交互 | WASD、鼠标、E/ESC/Tab | DoMove、DoLook、交互系统调用 |
|
||||
| 移动控制模块 | 通过 CMC 参数控制角色移动行为 | DoMove 方向值 + bIsInteracting 标志 | 角色位置/旋转更新 |
|
||||
| 摄像机模块 | 通过 SpringArm 参数控制摄像机跟随和碰撞 | Controller 旋转 + 碰撞检测结果 | 摄像机位置/旋转 |
|
||||
| 角色状态模块 | 维护交互状态标志,提供查询接口 | 交互系统的 SetInteracting 调用 | IsInteracting/IsRunning 查询结果 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 类设计图
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AChildHoodCharacter {
|
||||
-USpringArmComponent* CameraBoom
|
||||
-UCameraComponent* FollowCamera
|
||||
-UInputAction* MoveAction
|
||||
-UInputAction* LookAction
|
||||
-UInputAction* MouseLookAction
|
||||
-UInputAction* InteractAction
|
||||
-UInputAction* CancelAction
|
||||
-UInputAction* SwitchInteractAction
|
||||
-bool bIsInteracting
|
||||
+DoMove(float Right, float Forward) void
|
||||
+DoLook(float Yaw, float Pitch) void
|
||||
+SetInteracting(bool bValue) void
|
||||
+IsInteracting() bool
|
||||
+IsRunning() bool
|
||||
+GetFollowCamera() UCameraComponent*
|
||||
}
|
||||
|
||||
class AChildHoodPlayerController {
|
||||
-TArray~UInputMappingContext*~ DefaultMappingContexts
|
||||
#BeginPlay() void
|
||||
#SetupInputComponent() void
|
||||
}
|
||||
|
||||
class USpringArmComponent {
|
||||
+TargetArmLength float
|
||||
+SocketOffset FVector
|
||||
+bEnableCameraLag bool
|
||||
+CameraLagSpeed float
|
||||
+bDoCollisionTest bool
|
||||
+ProbeSize float
|
||||
}
|
||||
|
||||
class UCharacterMovementComponent {
|
||||
+MaxWalkSpeed float
|
||||
+MaxAcceleration float
|
||||
+BrakingDecelerationWalking float
|
||||
+RotationRate FRotator
|
||||
+WalkableFloorAngle float
|
||||
+bOrientRotationToMovement bool
|
||||
}
|
||||
|
||||
AChildHoodCharacter *-- USpringArmComponent : 组合(持有)
|
||||
AChildHoodCharacter *-- UCharacterMovementComponent : 组合(继承自带)
|
||||
AChildHoodCharacter --> AChildHoodPlayerController : 关联(Controller)
|
||||
```
|
||||
|
||||
### 新增类
|
||||
|
||||
无新增类。v0.1 角色控制系统不引入新类或新组件。
|
||||
|
||||
### 修改类
|
||||
|
||||
| 类名 | 修改内容 |
|
||||
|------|---------|
|
||||
| `AChildHoodCharacter` | ① 删除 `JumpAction` 成员及跳跃相关绑定/函数 ② 新增 `InteractAction`/`CancelAction`/`SwitchInteractAction` IA 指针 ③ 新增 `bIsInteracting` 标志 ④ `DoMove()` 添加交互状态检查 ⑤ 新增 `SetInteracting()`/`IsInteracting()`/`IsRunning()` 接口 ⑥ 调整 CMC/SpringArm 构造函数参数 |
|
||||
| `AChildHoodPlayerController` | `BeginPlay()` 中设置 `PlayerCameraManager` 的 Pitch 限幅 |
|
||||
|
||||
### 新增蓝图
|
||||
|
||||
无新增蓝图。v0.1 角色控制系统不创建新蓝图资产。
|
||||
|
||||
---
|
||||
|
||||
## 4. 时序图(仅复杂特性)
|
||||
|
||||
> ⚠️ **跳过**。角色控制系统为纯参数配置 + 简单标志管理,不涉及 3+ 系统协调或复杂分支流程。跨系统交互的时序图在交互系统技术设计文档中绘制。
|
||||
|
||||
---
|
||||
|
||||
## 5. 核心数据结构
|
||||
|
||||
### 角色控制无新增枚举或结构体
|
||||
|
||||
v0.1 角色控制系统不引入新的枚举、结构体或配置数据类。所有配置通过 CMC 和 SpringArm 内置属性完成。
|
||||
|
||||
### AChildHoodCharacter 关键数据定义
|
||||
|
||||
```cpp
|
||||
UCLASS(abstract)
|
||||
class AChildHoodCharacter : public ACharacter
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// === 配置参数(构造函数设置默认值) ===
|
||||
// 无额外配置参数,全部通过 CMC/SpringArm 内置属性配置
|
||||
|
||||
// === 输入动作(蓝图可覆盖) ===
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* MoveAction; // WASD/方向键移动
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* LookAction; // 手柄视角
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* MouseLookAction; // 鼠标视角
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* InteractAction; // E 键交互(委托交互系统)
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* CancelAction; // ESC 取消(委托交互系统)
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* SwitchInteractAction; // Tab/滚轮切换交互物(委托交互系统)
|
||||
|
||||
// === 运行时状态 ===
|
||||
bool bIsInteracting = false; // 是否正在交互中
|
||||
|
||||
// === 关键接口 ===
|
||||
|
||||
// 移动(交互中忽略输入)
|
||||
UFUNCTION(BlueprintCallable, Category="Input")
|
||||
virtual void DoMove(float Right, float Forward);
|
||||
|
||||
// 视角旋转
|
||||
UFUNCTION(BlueprintCallable, Category="Input")
|
||||
virtual void DoLook(float Yaw, float Pitch);
|
||||
|
||||
// 交互状态控制(供交互系统调用)
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetInteracting(bool bValue);
|
||||
|
||||
// 状态查询(供交互系统/UI 使用)
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
bool IsInteracting() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
bool IsRunning() const;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 行为规则 → 实现方案映射
|
||||
## 6. 行为规则 → 实现方案映射
|
||||
|
||||
### 一、摄像机系统
|
||||
|
||||
@@ -57,12 +245,12 @@ AChildHoodPlayerController
|
||||
|
||||
```cpp
|
||||
// AChildHoodCharacter 构造函数
|
||||
CameraBoom->TargetArmLength = 350.0f; // 3.5m 距离
|
||||
CameraBoom->TargetArmLength = 350.0f; // 3.5m 距离
|
||||
CameraBoom->SocketOffset = FVector(0.f, 0.f, 80.f); // 0.8m 高于角色
|
||||
// 初始俯角由 Controller Pitch 控制,在 PlayerController 中设置初始旋转
|
||||
// 俯角由 Controller Pitch 初始值和玩家操作决定,PlayerCameraManager 限制范围
|
||||
```
|
||||
|
||||
**可调参数**:TargetArmLength, SocketOffset.Z
|
||||
**可调参数**:`TargetArmLength`(2.5-5.0m),`SocketOffset.Z`(0.5-1.2m)
|
||||
|
||||
---
|
||||
|
||||
@@ -72,36 +260,37 @@ CameraBoom->SocketOffset = FVector(0.f, 0.f, 80.f); // 0.8m 高于角色
|
||||
|
||||
```cpp
|
||||
CameraBoom->bEnableCameraLag = true;
|
||||
CameraBoom->CameraLagSpeed = 6.0f; // 可调,范围 2-8
|
||||
CameraBoom->CameraLagSpeed = 6.0f; // 可调,范围 2-8
|
||||
CameraBoom->bEnableCameraRotationLag = false; // v0.1 不启用旋转延迟
|
||||
```
|
||||
|
||||
**可调参数**:CameraLagSpeed
|
||||
**可调参数**:`CameraLagSpeed`(2-8)
|
||||
|
||||
---
|
||||
|
||||
#### C3. 视角旋转(水平 150°/s,垂直 +45°/-30°)
|
||||
|
||||
**水平旋转实现**:通过 Enhanced Input IA 的 Value 值 × PlayerController::InputYawScale 控制。
|
||||
**水平旋转**:通过 Enhanced Input IA 的 Scale 值 × `AddControllerYawInput` 控制。
|
||||
|
||||
> 键鼠模式下鼠标移动是相对输入,由玩家手速决定实际旋转速度。执行案中 150°/s 是手柄摇杆的设计参考值,v0.1 优先键鼠,此参数暂不在代码中硬性限制。
|
||||
|
||||
**垂直限幅**:在 `AChildHoodPlayerController::BeginPlay()` 中设置
|
||||
|
||||
```cpp
|
||||
// InputYawScale 在 PlayerController 中设置
|
||||
// 灵敏度通过 IA 的 Scale 值控制,不需要自定义旋转速度限制
|
||||
// UE5 鼠标输入是相对移动,不受固定 °/s 限制
|
||||
// v0.1 使用默认鼠标输入灵敏度,后续版本可加灵敏度滑块
|
||||
void AChildHoodPlayerController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
// 设置摄像机俯仰角限制
|
||||
if (PlayerCameraManager)
|
||||
{
|
||||
PlayerCameraManager->ViewPitchMin = -30.0f; // 向下看最多 30°
|
||||
PlayerCameraManager->ViewPitchMax = 45.0f; // 向上看最多 45°
|
||||
}
|
||||
// ... 原有移动端触控逻辑
|
||||
}
|
||||
```
|
||||
|
||||
**垂直限幅实现**:在 CameraManager 中设置
|
||||
|
||||
```cpp
|
||||
// AChildHoodPlayerController::BeginPlay 或构造函数中
|
||||
PlayerCameraManager->ViewPitchMin = -30.0f; // 向下看最多 30°
|
||||
PlayerCameraManager->ViewPitchMax = 45.0f; // 向上看最多 45°
|
||||
```
|
||||
|
||||
> 注:执行案中 150°/s 是手柄摇杆的设计参考值。键鼠模式下鼠标移动是相对输入,由玩家手速决定实际旋转速度。v0.1 优先键鼠,此参数暂不在代码中硬性限制。
|
||||
|
||||
**可调参数**:ViewPitchMin, ViewPitchMax, IA Scale
|
||||
**可调参数**:`ViewPitchMin`(-45° ~ -20°),`ViewPitchMax`(+30° ~ +60°),IA Scale
|
||||
|
||||
---
|
||||
|
||||
@@ -111,33 +300,32 @@ PlayerCameraManager->ViewPitchMax = 45.0f; // 向上看最多 45°
|
||||
|
||||
```cpp
|
||||
CameraBoom->bDoCollisionTest = true;
|
||||
CameraBoom->ProbeSize = 12.0f; // 碰撞探针半径
|
||||
CameraBoom->ProbeChannel = ECC_Camera; // 使用 Camera 碰撞通道
|
||||
|
||||
// 最小距离保证:SpringArm 自动缩短到碰撞面
|
||||
// 当目标位置被阻挡时,SpringArm 将摄像机移到最近的未阻挡位置
|
||||
// 默认行为已满足"紧贴碰撞面内侧"的要求
|
||||
CameraBoom->ProbeSize = 12.0f; // 碰撞探针半径
|
||||
CameraBoom->ProbeChannel = ECC_Camera; // 使用 Camera 碰撞通道
|
||||
```
|
||||
|
||||
**最小距离保证**(0.5m):SpringArm 的 `TargetArmLength` 最短会被碰撞面推到约 0(取决于探针半径和角色胶囊体大小)。如需严格保证 0.5m 最小距离,可在蓝图中加 Tick 检查后处理。**v0.1 先用原生行为,视体验再决定是否添加。**
|
||||
- SpringArm 自动缩短摄像机到碰撞面内侧
|
||||
- 碰撞消除后配合 Camera Lag 平滑恢复到 `TargetArmLength`
|
||||
- v0.1 仅处理静态场景几何体碰撞,不处理动态物体
|
||||
- 最小距离保证(0.5m):v0.1 先用原生行为,视实际体验决定是否添加 Tick 后处理
|
||||
|
||||
**恢复**:碰撞消除后 SpringArm 自动恢复到 TargetArmLength,配合 Camera Lag 实现平滑回位。
|
||||
|
||||
**v0.1 简化**:仅处理与静态几何体碰撞(默认行为),不处理动态物体。
|
||||
**可调参数**:`ProbeSize`(8-20),`bDoCollisionTest`
|
||||
|
||||
---
|
||||
|
||||
#### C5. 跑动中角色始终背对摄像机
|
||||
|
||||
**实现**:已有配置满足
|
||||
**实现**:已有配置满足,调整 `RotationRate`
|
||||
|
||||
```cpp
|
||||
bUseControllerRotationYaw = false; // 角色不跟随 Controller Yaw
|
||||
GetCharacterMovement()->bOrientRotationToMovement = true; // 角色朝移动方向旋转
|
||||
bUseControllerRotationYaw = false; // 角色不跟随 Controller Yaw
|
||||
GetCharacterMovement()->bOrientRotationToMovement = true; // 角色朝移动方向旋转
|
||||
GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f); // 转向速度 720°/s
|
||||
```
|
||||
|
||||
角色转向速度 720°/s 远快于鼠标旋转速度,自然满足"摄像机追不到角色正面"的效果。无需额外逻辑。
|
||||
角色转向速度 720°/s 远快于鼠标旋转速度(150°/s),自然满足"摄像机追不到角色正面"。
|
||||
|
||||
**可调参数**:`RotationRate.Yaw`(360-1080°/s)
|
||||
|
||||
---
|
||||
|
||||
@@ -145,38 +333,39 @@ GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f); // 转向速
|
||||
|
||||
#### M1. 移动方向(相对摄像机,对角 45° 合成)
|
||||
|
||||
**实现**:已有 `DoMove()` 逻辑满足
|
||||
**实现**:已有 `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);
|
||||
if (GetController() != nullptr)
|
||||
{
|
||||
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 内部归一化)
|
||||
- 连续旋转中移动方向实时跟随摄像机朝向(每帧重新计算方向)
|
||||
|
||||
**无需修改。**
|
||||
- 对角输入(W+A)由 Enhanced Input 2D Axis 自然处理
|
||||
- `AddMovementInput` 内部归一化,斜向速度不叠加
|
||||
- 每帧重新计算方向,连续旋转中移动方向实时跟随摄像机
|
||||
|
||||
---
|
||||
|
||||
#### M2. 角色转向(720°/s,最短路径,边跑边转)
|
||||
|
||||
**实现**:CMC 参数配置
|
||||
**实现**:CMC 参数配置(同 C5)
|
||||
|
||||
```cpp
|
||||
GetCharacterMovement()->bOrientRotationToMovement = true;
|
||||
GetCharacterMovement()->RotationRate = FRotator(0.f, 720.f, 0.f);
|
||||
```
|
||||
|
||||
CMC 默认走最短路径旋转,转向期间角色持续移动(不"停顿再转向")。**无需修改。**
|
||||
CMC 默认最短路径旋转,转向期间角色持续移动。**无需额外修改。**
|
||||
|
||||
---
|
||||
|
||||
@@ -184,87 +373,89 @@ CMC 默认走最短路径旋转,转向期间角色持续移动(不"停顿再
|
||||
|
||||
**速度**:
|
||||
```cpp
|
||||
GetCharacterMovement()->MaxWalkSpeed = 450.0f; // 4.5 m/s (UE5 1uu = 1cm)
|
||||
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 是起始值,实际手感需测试微调。
|
||||
> 注:CMC 加速不是严格线性,受 `GroundFriction` 等因素影响。2250 是起始值,需实测微调。
|
||||
|
||||
**可调参数**:`MaxWalkSpeed`(3.5-6.0 m/s),`MaxAcceleration`(1000-4000 cm/s²)
|
||||
|
||||
---
|
||||
|
||||
#### M4. 停止减速(0.3s)
|
||||
|
||||
**实现**:
|
||||
|
||||
```cpp
|
||||
// 从 450 到 0 cm/s 在 0.3s → 减速度 = 450/0.3 = 1500 cm/s²
|
||||
GetCharacterMovement()->BrakingDecelerationWalking = 1500.0f;
|
||||
```
|
||||
|
||||
> 同样受 GroundFriction 影响,1500 是起始值。
|
||||
> 同样受 `GroundFriction` 影响,1500 是起始值。
|
||||
|
||||
**可调参数**:`BrakingDecelerationWalking`(800-2500 cm/s²)
|
||||
|
||||
---
|
||||
|
||||
#### M5. 坡道与台阶(坡度 ≤45°,台阶 ≤0.15m)
|
||||
|
||||
**实现**:
|
||||
|
||||
```cpp
|
||||
GetCharacterMovement()->WalkableFloorAngle = 45.0f; // 最大可行走坡度
|
||||
// 台阶高度由胶囊体半径和 CMC 的 StepHeight 决定
|
||||
// 默认 StepOffset = 45.0f (4.5cm),覆盖 0.15m 需要调大
|
||||
// 但 v0.1 场景设计避免高台阶,先保持默认
|
||||
GetCharacterMovement()->SetWalkableFloorAngle(45.0f);
|
||||
// 台阶:v0.1 场景设计避免高台阶,CMC 默认 StepOffset 可覆盖常规台阶
|
||||
```
|
||||
|
||||
**可调参数**:`WalkableFloorAngle`(30°-60°)
|
||||
|
||||
---
|
||||
|
||||
### 三、输入映射
|
||||
|
||||
#### I1. WASD/方向键 → 移动
|
||||
|
||||
**实现**:已有 IA_Move + IMC 配置。保持不变。
|
||||
已有 `IA_Move` + IMC 配置,保持不变。
|
||||
|
||||
#### I2. 鼠标移动 → 视角旋转
|
||||
|
||||
**实现**:已有 IA_MouseLook + IMC 配置。保持不变。
|
||||
已有 `IA_MouseLook` + IMC 配置,保持不变。
|
||||
|
||||
#### I3. E/ESC/Tab/滚轮 → 委托交互系统
|
||||
|
||||
**实现**:在 Character 中添加交互相关 IA 指针和绑定
|
||||
**实现**:在 `AChildHoodCharacter` 中新增交互相关 IA 指针
|
||||
|
||||
```cpp
|
||||
// 新增成员(AChildHoodCharacter.h)
|
||||
// AChildHoodCharacter.h 新增成员
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* InteractAction; // E 键
|
||||
UInputAction* InteractAction; // E 键
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* CancelAction; // ESC 键
|
||||
UInputAction* CancelAction; // ESC 键
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* SwitchInteractAction; // Tab 键
|
||||
UInputAction* SwitchInteractAction; // Tab 键 / 鼠标滚轮
|
||||
|
||||
// SetupPlayerInputComponent 中绑定
|
||||
// 回调函数直接调用 InteractionManager 的对应接口
|
||||
// 回调函数直接调用交互系统的对应接口(具体实现见交互系统技术设计文档)
|
||||
```
|
||||
|
||||
> 具体回调实现见交互系统技术设计文档。
|
||||
> IMC 中需新增 `IA_Interact`/`IA_Cancel`/`IA_SwitchInteract` 的按键映射。
|
||||
|
||||
#### I4. 移除跳跃
|
||||
|
||||
**实现**:移除 JumpAction 及其绑定
|
||||
**实现**:删除跳跃相关代码
|
||||
|
||||
```cpp
|
||||
// 删除 JumpAction 成员
|
||||
// 删除成员
|
||||
// UPROPERTY(EditAnywhere, Category="Input") UInputAction* JumpAction;
|
||||
|
||||
// 删除 SetupPlayerInputComponent 中的 Jump 绑定
|
||||
// 删除 DoJumpStart/DoJumpEnd 函数
|
||||
// CMC: GetCharacterMovement()->JumpZVelocity 不需要设置(不跳跃)
|
||||
// 删除 DoJumpStart() / DoJumpEnd() 函数
|
||||
// CMC: 不需要设置 JumpZVelocity(不跳跃)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -276,43 +467,78 @@ UInputAction* SwitchInteractAction; // Tab 键
|
||||
**实现**:在 `DoMove()` 中添加状态检查
|
||||
|
||||
```cpp
|
||||
// 新增成员
|
||||
bool bIsInteracting = false;
|
||||
|
||||
// 修改 DoMove
|
||||
void AChildHoodCharacter::DoMove(float Right, float Forward)
|
||||
{
|
||||
if (bIsInteracting) return; // 交互中忽略移动
|
||||
if (bIsInteracting) return; // 交互中忽略移动
|
||||
// ... 原有逻辑
|
||||
}
|
||||
```
|
||||
|
||||
// 外部接口(供 InteractionManager 调用)
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetInteracting(bool bInteracting);
|
||||
```cpp
|
||||
void AChildHoodCharacter::SetInteracting(bool bValue)
|
||||
{
|
||||
bIsInteracting = bValue;
|
||||
}
|
||||
```
|
||||
|
||||
#### P2. 交互中摄像机控制权交接
|
||||
|
||||
**实现**:InteractionManager 在进入交互时通过 `SetViewTargetWithBlend` 切换摄像机目标;退出时切换回 Character。角色控制系统本身不需要修改摄像机逻辑。
|
||||
**实现**:交互系统通过 `SetViewTargetWithBlend` 切换摄像机目标,退出时切回 Character。角色控制系统本身不需要修改摄像机逻辑。
|
||||
|
||||
交互结束后摄像机自动回到 SpringArm 默认跟随(因为 ViewTarget 切回 Character,SpringArm 恢复控制)。
|
||||
交互结束后摄像机自动回到 SpringArm 默认跟随(ViewTarget 切回 Character 后 SpringArm 恢复控制)。
|
||||
|
||||
#### P3. 状态信号提供
|
||||
|
||||
**实现**:提供查询接口
|
||||
|
||||
```cpp
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
bool IsInteracting() const { return bIsInteracting; }
|
||||
bool AChildHoodCharacter::IsInteracting() const
|
||||
{
|
||||
return bIsInteracting;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
bool IsRunning() const;
|
||||
// IsRunning: GetVelocity().Size() > Threshold && GetCharacterMovement()->IsMovingOnGround()
|
||||
bool AChildHoodCharacter::IsRunning() const
|
||||
{
|
||||
return GetVelocity().SizeSquared() > 100.f // 速度 > 10 cm/s 阈值
|
||||
&& GetCharacterMovement()->IsMovingOnGround();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据流
|
||||
## 7. 美术资源需求
|
||||
|
||||
v0.1 角色控制系统**不直接需要**美术资产。以下为间接需求:
|
||||
|
||||
| 资源类型 | 名称 | 数量 | 规格 | 触发时机/用途 |
|
||||
|----------|------|------|------|---------------|
|
||||
| 占位动画 | Idle(站立待机) | 1 | 简单 T-pose 或 A-pose 即可 | 角色静止时播放;v0.1 可无动画 |
|
||||
| 占位动画 | Run(跑步循环) | 1 | 简单跑步循环 | 角色移动时播放;执行案明确"若无动画,角色滑动也可接受" |
|
||||
|
||||
> v0.1 不包含跳跃、蹲下、攀爬,不需要对应动画。
|
||||
|
||||
---
|
||||
|
||||
## 8. 技术风险与注意事项
|
||||
|
||||
| 风险 | 等级 | 说明 | 缓解措施 |
|
||||
|------|------|------|---------|
|
||||
| 软跟随手感不佳 | 🟢 低 | `CameraLagSpeed` 需要实际测试调整手感 | 多个预设值快速切换测试(推荐 4/6/8 三档) |
|
||||
| 摄像机角落穿墙 | 🟢 低 | 角落/窄空间 SpringArm 碰撞可能出现抖动 | 角落场景专项测试,必要时加大 ProbeSize |
|
||||
| CMC 加速/减速不符合预期 | 🟢 低 | CMC 物理模型不完全线性,受 `GroundFriction` 影响 | 参数范围已预留,实测微调 |
|
||||
| 720°/s 转向过快导致"飘" | 🟢 低 | 无正式动画时转向缺乏视觉过渡 | v0.1 可接受,后续配合动画调整 `RotationRate` |
|
||||
| 背对摄像机效果依赖转向速度比 | 🟢 低 | 若后续降低 `RotationRate` 或提高鼠标灵敏度,效果可能改变 | 保持 `RotationRate` 远大于鼠标旋转速度 |
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. **IMC 资产更新**:新增交互 IA 后需在 IMC 中添加对应按键映射(E/ESC/Tab),此为蓝图操作,不在 C++ 代码中。
|
||||
2. **跳跃移除的完整性**:移除跳跃时需同时检查蓝图中是否有 Jump 相关引用,避免编译警告。
|
||||
3. **bIsInteracting 的线程安全**:v0.1 为单线程游戏,不需要加锁。如后续引入多线程需重新评估。
|
||||
4. **IsRunning 阈值**:速度阈值 10 cm/s(`SizeSquared > 100`)为经验值,可能需要根据实际角色大小调整。
|
||||
|
||||
---
|
||||
|
||||
## 9. 数据流
|
||||
|
||||
### 配置参数流
|
||||
|
||||
@@ -320,8 +546,7 @@ bool IsRunning() const;
|
||||
C++ 构造函数默认值 → 蓝图派生类可覆盖 → 运行时通过 Details 面板微调
|
||||
```
|
||||
|
||||
v0.1 原型阶段所有参数在 C++ 中设置默认值,蓝图可覆盖。不使用 DataAsset 或配置表。
|
||||
批量生产阶段迁移到参数 DataAsset。
|
||||
v0.1 原型阶段所有参数在 C++ 中设置默认值,蓝图可覆盖。批量生产阶段迁移到参数 DataAsset。
|
||||
|
||||
### 运行时状态流
|
||||
|
||||
@@ -329,41 +554,17 @@ v0.1 原型阶段所有参数在 C++ 中设置默认值,蓝图可覆盖。不
|
||||
Enhanced Input (WASD/鼠标)
|
||||
→ AChildHoodPlayerController (IMC 注册)
|
||||
→ AChildHoodCharacter (IA 回调)
|
||||
├─ DoMove() → CMC (AddMovementInput)
|
||||
├─ DoLook() → Controller (AddYawInput/AddPitchInput)
|
||||
├─ DoMove() ─→ bIsInteracting? ─→ CMC (AddMovementInput)
|
||||
├─ DoLook() ─→ Controller (AddYawInput/AddPitchInput)
|
||||
│ → SpringArm (Controller Rotation)
|
||||
│ → Camera (位置/旋转)
|
||||
├─ InteractAction → InteractionManager (委托)
|
||||
└─ bIsInteracting → DoMove() (输入屏蔽)
|
||||
├─ InteractAction/CancelAction/SwitchInteractAction ─→ 交互系统(委托)
|
||||
└─ 交互系统 ─→ SetInteracting(bool) ─→ bIsInteracting 标志
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 美术资源需求
|
||||
|
||||
v0.1 角色控制系统**不直接需要**美术资产。以下为间接需求:
|
||||
|
||||
| 资源类型 | 名称 | 数量 | 规格 | 说明 |
|
||||
|----------|------|------|------|------|
|
||||
| 占位动画 | Idle(站立待机) | 1 | 简单 T-pose 或 A-pose 即可 | v0.1 可无动画 |
|
||||
| 占位动画 | Run(跑步循环) | 1 | 简单跑步循环,角色可在地面滑动 | 执行案明确说"若无动画资源,角色在地面滑动也可接受" |
|
||||
|
||||
> v0.1 角色控制不包含跳跃、蹲下、攀爬,因此不需要对应动画。
|
||||
|
||||
---
|
||||
|
||||
## 技术风险与注意事项
|
||||
|
||||
| 风险 | 等级 | 说明 | 缓解措施 |
|
||||
|------|------|------|---------|
|
||||
| 软跟随手感不佳 | 🟢 低 | CameraLagSpeed 需要实际测试调整 | 多个预设值快速切换测试 |
|
||||
| 摄像机碰撞穿墙 | 🟢 低 | SpringArm 原生碰撞处理基本满足 | 角落/窄空间需额外测试 |
|
||||
| CMC 加速/减速不符合预期 | 🟢 低 | CMC 物理模型不完全线性 | 参数范围已预留,微调即可 |
|
||||
| 角色转身"飘"的感觉 | 🟢 低 | 720°/s 偏快可能导致动画不自然 | v0.1 无正式动画,暂时不是问题 |
|
||||
|
||||
---
|
||||
|
||||
## 可调参数汇总
|
||||
## 10. 可调参数汇总
|
||||
|
||||
所有参数均在构造函数中设置默认值,蓝图可覆盖:
|
||||
|
||||
@@ -372,11 +573,60 @@ v0.1 角色控制系统**不直接需要**美术资产。以下为间接需求
|
||||
| 摄像机距离 | `CameraBoom->TargetArmLength` | 350.0f | 构造函数 |
|
||||
| 摄像机高度 | `CameraBoom->SocketOffset.Z` | 80.0f | 构造函数 |
|
||||
| 跟随速度 | `CameraBoom->CameraLagSpeed` | 6.0f | 构造函数 |
|
||||
| 碰撞检测 | `CameraBoom->bDoCollisionTest` | true | 构造函数 |
|
||||
| 碰撞探针 | `CameraBoom->ProbeSize` | 12.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 | 构造函数 |
|
||||
|
||||
---
|
||||
|
||||
## 11. 文件结构
|
||||
|
||||
```
|
||||
Source/ChildHood/
|
||||
├── ChildHoodCharacter.h # 修改:新增交互 IA、状态标志、查询接口;移除跳跃
|
||||
├── ChildHoodCharacter.cpp # 修改:调整 CMC/SpringArm 参数;修改 DoMove;移除跳跃
|
||||
├── ChildHoodPlayerController.h # 不修改
|
||||
└── ChildHoodPlayerController.cpp # 修改:BeginPlay 中设置 Pitch 限幅
|
||||
|
||||
Content/
|
||||
├── Input/
|
||||
│ ├── IMC_Default.umap # 修改:新增 IA_Interact/IA_Cancel/IA_SwitchInteract 映射
|
||||
│ ├── IA_Interact.uasset # 新增:E 键交互输入动作
|
||||
│ ├── IA_Cancel.uasset # 新增:ESC 取消输入动作
|
||||
│ └── IA_SwitchInteract.uasset # 新增:Tab/滚轮切换输入动作
|
||||
└── Blueprints/
|
||||
└── BP_ChildHoodCharacter # 可能修改:绑定新增 IA 到蓝图属性(若使用蓝图派生)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 工期预估与实现拆分
|
||||
|
||||
### 工作量估算
|
||||
|
||||
| 维度 | 估算 |
|
||||
|------|------|
|
||||
| 总工期 | 1-2 天 |
|
||||
| 修改 C++ 代码 | 约 60-80 行(净增 30 行 + 删除 20 行) |
|
||||
| 新增蓝图 | 3 个 InputAction 资产 + IMC 修改 |
|
||||
| 实现复杂度 | 低 |
|
||||
|
||||
### 实现拆分建议
|
||||
|
||||
| 子任务 | 内容 | 预估时间 | 依赖 | 验证方式 |
|
||||
|--------|------|---------|------|---------|
|
||||
| 6a-1 | 移除跳跃:删除 JumpAction、绑定、函数 | 0.5h | 无 | 编译通过 + 角色不跳跃 |
|
||||
| 6a-2 | 调整 CMC/SpringArm 构造函数参数 | 0.5h | 无 | PIE 中测试移动手感、摄像机跟随 |
|
||||
| 6a-3 | 添加 Pitch 限幅(PlayerController BeginPlay) | 0.5h | 无 | PIE 中测试鼠标上下看限幅 |
|
||||
| 6a-4 | 新增交互状态管理(bIsInteracting + Set/Get) | 0.5h | 无 | 编译通过 + 蓝图可调用 |
|
||||
| 6a-5 | 新增交互 IA 绑定(3 个 InputAction + IMC 修改) | 1h | 6a-4 | PIE 中按 E/ESC/Tab 无报错(回调委托给交互系统) |
|
||||
| 6a-6 | 修改 DoMove 添加交互状态检查 | 0.5h | 6a-4 | 交互中按 WASD 角色不移动 |
|
||||
| 6a-7 | 综合测试:手感微调 + 碰撞测试 + 边界情况 | 1-2h | 6a-1~6 | 全功能验证 |
|
||||
|
||||
> **总预估**:4-5 小时(约 1 个工作日)。预留半天调参和边界测试。
|
||||
|
||||
Reference in New Issue
Block a user