【AI编码】补充文档

main
刘涛 2026-02-05 14:52:22 +08:00
parent 7c4000b5c9
commit 15ef71cfe6
1 changed files with 393 additions and 0 deletions

View File

@ -0,0 +1,393 @@
# 暂停状态下技能释放流程说明
> 本文档由 AI 生成,用于说明暂停状态下玩家主动释放技能的完整流程逻辑。
## 功能概述
在战斗暂停状态下,玩家可以为多个单位预先选择技能释放位置。这些技能会被**缓存**起来,等到**解除暂停**后统一释放执行。
**核心特点**
- 暂停时选择技能 → 缓存到字典
- 解除暂停时 → 统一发送释放事件
- 支持覆盖、取消已缓存的技能
---
## 核心类职责
| 类名 | 职责 |
|------|------|
| `SkillAreaSelector2` | 技能区域选择器,处理预览、选择、取消 |
| `SkillPauseCacheManager` | 暂停时技能缓存管理器,存储已缓存的技能数据 |
| `InPauseCacheSkillArea` | 显示已缓存技能的释放位置(特殊显示逻辑) |
| `GroundPlaneManager` | 地面面片管理器,负责实际的地面显示 |
| `CommonSkillAreaSelector` | 基类,处理暂停/恢复、事件注册 |
| `FightSkillPutManager` | 技能释放UI管理器 |
---
## 技能释放类型枚举
**文件**`Assets/Code/Scripts/GamePlay/Area/Skill/SkillAreaSelector2.cs`
```csharp
public enum ECacheUseType
{
RealUse, // 非暂停时,真正释放
CacheUse, // 暂停时,缓存技能
Cancel, // 取消技能选择
}
```
---
## 完整流程
### 阶段1进入技能预览
**入口方法**`SkillAreaSelector2.EnterPreview(SkillHandle skill)`
```csharp
public void EnterPreview(SkillHandle skill)
{
// 隐藏其他区域显示
AreaManager.instance.moveAreaView.Hide();
AreaManager.instance.investigateAreaView.Hide();
AreaManager.instance.attackArea.HideArea();
skillHandle = skill;
// 通知UI打开界面
FightSkillPutManager.Instance.EnterSkillPut(skill.owner);
// 暂停游戏(记录当前速度)
_PauseGame();
// 计算技能范围、创建区域显示
_CalcSkillCellIndex();
_CreateSkillAreaBoard();
// 显示屏幕特效
SkillManager.instance.screenEffect.Show();
// 预选格子和单位
_PreSelectCellIndex();
_PreSelectUnits();
_AttachHighlights();
// 注册事件监听
_RegisterEvents();
}
```
### 阶段2确认技能释放
**方法**`SkillAreaSelector2._OnEventClickCellIndex(int cellIndex)`
```csharp
protected override void _OnEventClickCellIndex(int cellIndex)
{
if (!_preSelectCellIndexList.Contains(cellIndex))
{
UITipsManager.ShowTips("无法在此处释放技能", EShowTipType.Error);
return;
}
var cacheSkillHandle = skillHandle;
if (_oldTimeSpeed == 0) // 之前是暂停状态
{
// 取消选中
LevelManager.Instance.CurrentLevel.UnSelectUnit();
// 暂停状态下不能释放技能, 改为暂存
ExitPreview(ECacheUseType.CacheUse).Forget();
var eventData = new EventDataUseSkill()
{
sender = cacheSkillHandle.owner,
pointCellIndex = cellIndex,
};
EventManager.Instance.Send(EventManager.EventName.UI_CACHE_SKILL, eventData);
}
else // 之前是运行状态
{
ExitPreview(ECacheUseType.RealUse).Forget();
var eventData = new EventDataUseSkill()
{
sender = cacheSkillHandle.owner,
pointCellIndex = cellIndex,
};
EventManager.Instance.Send(EventManager.EventName.UI_USE_SKILL, eventData);
}
}
```
### 阶段3缓存技能
**文件**`Assets/Code/Scripts/GamePlay/Level/SkillPauseCache/SkillPauseCacheManager.cs`
```csharp
private void OnCacheSkill(EventDataUseSkill eventDataUseSkill)
{
// 使用字典索引器相同key会自动覆盖
dicCacheSkill[eventDataUseSkill.sender] = eventDataUseSkill;
// 设置目标格子
eventDataUseSkill.sender.controlData.targetCellIndex = eventDataUseSkill.sender.transData.cellIndex;
eventDataUseSkill.sender.controlData.moveTargetCellIndex = eventDataUseSkill.sender.transData.cellIndex;
// 触发对话事件
if (EGameUnitType.Character == eventDataUseSkill.sender.gameunitType)
DialogueManager.Instance.OnFightUseSkill(eventDataUseSkill.sender);
}
```
### 阶段4解除暂停时释放
```csharp
private void OnPauseStateChange()
{
if (ELevelSpeed.Level_0 == curLevel.GetSpeed())
return;
// 遍历所有缓存的技能,发送释放事件
foreach (EventDataUseSkill eventDataUseSkill in dicCacheSkill.Values)
{
EventManager.Instance.Send(EventManager.EventName.UI_USE_SKILL, eventDataUseSkill);
}
// 清空缓存
dicCacheSkill.Clear();
// 发送指挥官技能缓存事件
EventManager.Instance.Send(EventManager.EventName.UseCacheCommanderSkill);
}
```
---
## 特殊显示逻辑
### InPauseCacheSkillArea 类
**文件**`Assets/Code/Scripts/GamePlay/Area/Skill/InPauseCacheSkillArea.cs`
**功能**:当玩家在暂停状态下选中一个已缓存技能的单位时,在地面上显示该单位技能将要释放的位置。
#### 事件监听
| 事件 | 处理方法 | 作用 |
|------|---------|------|
| `INFIGHT_PAUSE_CHANGED` | `_OnPauseChanged()` | 监听暂停状态变化 |
| `LevelUnitSelect` | `_OnUnitSelected()` | 选中单位时尝试显示缓存技能区域 |
| `LevelUnitUnSelect` | `_OnUnitUnSelected()` | 取消选中时隐藏显示 |
#### 显示流程
```csharp
private void _ShowCachedSkillArea()
{
// 1. 清除旧的显示
GroundPlaneManager.Instance.UnregisterPlanes(this);
if (_selectedUnit == null)
return;
// 2. 获取单位的技能管理器
var unitSkillManager = SkillManager.instance.GetUnitSkillManager(_selectedUnit);
// 3. 获取主动技能
var skillHandle = unitSkillManager.positiveSkill;
// 4. 获取技能的显示区域ID
var showAreaId = skillHandle.runtimeData.configData.ShowAreaId;
// 5. 查询缓存数据
if (!SkillPauseCacheManager.Ins.TryGetChcheSkillData(_selectedUnit, out var skillData))
{
return; // 无缓存数据,不显示
}
// 6. 计算技能影响的格子列表
var getAreaCellIndexList = AreaManager.instance.GetCellIndexs(skillData.pointCellIndex, showAreaId);
// 7. 注册地面显示
GroundPlaneManager.Instance.RegisterPlanes(
getAreaCellIndexList,
GroundPlaneType.InPauseCacheSkill, // 专用显示类型
this
);
}
```
#### 显示资源
- **类型**`GroundPlaneType.InPauseCacheSkill`
- **Prefab**`Assets/Art_Out/Other/SkillArea/skill_inpause_preview_point.prefab`
---
## 缓存技能的覆盖逻辑
当一个单位**已经缓存了技能**,玩家**再次为该单位选择技能释放位置**时,会直接**覆盖**之前的缓存数据。
### 覆盖机制
```csharp
// 使用字典的索引器赋值如果key已存在则覆盖
dicCacheSkill[eventDataUseSkill.sender] = eventDataUseSkill;
```
### 覆盖流程示例
| 步骤 | 操作 | dicCacheSkill 状态 |
|------|------|-------------------|
| 1 | 为单位A选择释放点(格子100) | `{ A → 格子100 }` |
| 2 | 再次为单位A选择释放点(格子200) | `{ A → 格子200 }` (覆盖) |
| 3 | 解除暂停 | 技能释放到格子200 |
### 设计特点
| 特点 | 说明 |
|------|------|
| **自动覆盖** | 使用字典索引器相同key自动覆盖 |
| **无确认提示** | 覆盖时不会提示玩家 |
| **每单位一个缓存** | 字典以 `GameUnit` 为key每个单位最多只能缓存一个技能释放数据 |
| **对话重新触发** | 覆盖时会再次调用 `DialogueManager.OnFightUseSkill` |
---
## 取消缓存技能的方式
| 方式 | 触发条件 | 处理逻辑 |
|------|---------|---------|
| **移动指令取消** | 给单位下达移动指令 | `INFIGHT_AUDIO_CLICK_MOVE` 事件 → `OnClearSkillCache()``dicCacheSkill.Remove(unit)` |
| **解除暂停释放** | 游戏恢复运行 | 遍历缓存发送 `UI_USE_SKILL` → 清空缓存 |
| **取消技能选择** | 点击取消按钮 | `ExitPreview(Cancel)` → 退出预览,不修改已有缓存 |
### 移动指令取消
**文件**`Assets/Code/Scripts/GamePlay/AI/AIManager.Directive.cs`
```csharp
if (isPlayerOperate && unit is UnitCharacter character)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_AUDIO_CLICK_MOVE, character);
}
```
**文件**`Assets/Code/Scripts/GamePlay/Level/SkillPauseCache/SkillPauseCacheManager.cs`
```csharp
private void OnClearSkillCache(GameUnit gameUnit)
{
dicCacheSkill.Remove(gameUnit);
}
```
---
## 关键事件
| 事件名 | 触发时机 | 处理者 | 结果 |
|--------|---------|--------|------|
| `UI_CACHE_SKILL` | 暂停时确认技能释放点 | `SkillPauseCacheManager` | 缓存技能数据 |
| `UI_USE_SKILL` | 非暂停时选择 / 解除暂停时 | `SkillManager` | 真正释放技能 |
| `INFIGHT_UI_CANCEL_USE_SKILL` | 点击取消按钮 | `SkillAreaSelector2` | 退出技能预览 |
| `INFIGHT_AUDIO_CLICK_MOVE` | 玩家操作单位移动 | `SkillPauseCacheManager` | 清除该单位的缓存技能 |
| `LevelFightUIPauseChange` | 暂停状态变化 | `SkillPauseCacheManager` | 解除暂停时释放所有缓存 |
| `LevelSpeedChange` | 游戏速度变化 | `SkillPauseCacheManager` | 解除暂停时释放所有缓存 |
| `LevelUnitSelect` | 选中单位 | `InPauseCacheSkillArea` | 显示该单位的缓存技能区域 |
| `LevelUnitUnSelect` | 取消选中 | `InPauseCacheSkillArea` | 隐藏缓存技能区域显示 |
| `INFIGHT_PAUSE_CHANGED` | 暂停状态变化 | `InPauseCacheSkillArea` | 解除暂停时隐藏显示 |
---
## 关键数据结构
### SkillPauseCacheManager.dicCacheSkill
```csharp
Dictionary<GameUnit, EventDataUseSkill> dicCacheSkill;
```
### EventDataUseSkill
```csharp
public class EventDataUseSkill
{
public GameUnit sender; // 释放技能的单位
public int pointCellIndex; // 技能释放的目标格子
}
```
---
## 流程总结图
```
玩家操作 系统响应
─────────────────────────────────────────────────────────────────────
① 暂停状态下点击角色技能 → 进入技能预览
├─ 暂停游戏
├─ 显示技能范围
└─ 等待玩家选择
② 选择释放位置并确认 → 缓存技能 + 取消选中
├─ dicCacheSkill[unit] = data
└─ UnSelectUnit()
③ 再次点击该单位 → 显示缓存技能区域
└─ GroundPlaneManager 显示
skill_inpause_preview_point
④ 点击其他单位/取消选中 → 隐藏缓存技能区域
└─ GroundPlaneManager 隐藏
⑤ 再次为该单位选择技能 → 覆盖缓存技能
└─ dicCacheSkill[unit] = newData
⑥ 给该单位下达移动指令 → 取消该单位的缓存技能
└─ dicCacheSkill.Remove(unit)
⑦ 解除暂停 → 释放所有缓存技能
├─ 遍历发送 UI_USE_SKILL
├─ 清空 dicCacheSkill
└─ 隐藏所有缓存区域显示
```
---
## 相关代码文件
| 文件路径 | 说明 |
|---------|------|
| `Assets/Code/Scripts/GamePlay/Area/Skill/SkillAreaSelector2.cs` | 技能区域选择器 |
| `Assets/Code/Scripts/GamePlay/Area/Skill/CommonSkillAreaSelector.cs` | 技能区域选择器基类 |
| `Assets/Code/Scripts/GamePlay/Area/Skill/InPauseCacheSkillArea.cs` | 暂停状态缓存技能区域显示 |
| `Assets/Code/Scripts/GamePlay/Level/SkillPauseCache/SkillPauseCacheManager.cs` | 技能暂停缓存管理器 |
| `Assets/Code/Scripts/GamePlay/Skill/SkillManager.cs` | 技能管理器 |
| `Assets/Code/Scripts/GamePlay/Skill/FightSkillPutManager.cs` | 技能释放UI管理器 |
| `Assets/Code/Scripts/GamePlay/UI/LevelFight/FightSceneUI/UISkillPutController.cs` | 技能释放UI控制器 |
| `Assets/Code/Scripts/GamePlay/GroundPlane/GroundPlaneManager.cs` | 地面面片管理器 |
| `Assets/Code/Scripts/GamePlay/GroundPlane/GroundPlaneType.cs` | 地面面片类型枚举 |
| `Assets/Code/Scripts/GamePlay/Common/PathDefine.cs` | 路径定义(包含预制体路径) |
| `Assets/Code/Scripts/GamePlay/AI/AIManager.Directive.cs` | AI指令管理移动指令触发取消缓存 |
---
## 注意事项
1. **显示时机**:只有在暂停状态下选中已缓存技能的单位时才会显示缓存区域
2. **自动隐藏**:解除暂停时会自动隐藏所有缓存区域显示
3. **资源预加载**`skill_inpause_preview_point.prefab` 在关卡加载时预加载
4. **每单位限制**:每个单位最多只能缓存一个技能,再次选择会覆盖
5. **取消选中**:确认技能释放点后会自动取消选中该单位,方便玩家继续操作其他单位
---
*文档生成时间2026-02-05*
*生成工具Cursor AI Agent*