13 KiB
13 KiB
暂停状态下技能释放流程说明
本文档由 AI 生成,用于说明暂停状态下玩家主动释放技能的完整流程逻辑。
功能概述
在战斗暂停状态下,玩家可以为多个单位预先选择技能释放位置。这些技能会被缓存起来,等到解除暂停后统一释放执行。
核心特点:
- 暂停时选择技能 → 缓存到字典
- 解除暂停时 → 统一发送释放事件
- 支持覆盖、取消已缓存的技能
核心类职责
| 类名 | 职责 |
|---|---|
SkillAreaSelector2 |
技能区域选择器,处理预览、选择、取消 |
SkillPauseCacheManager |
暂停时技能缓存管理器,存储已缓存的技能数据 |
InPauseCacheSkillArea |
显示已缓存技能的释放位置(特殊显示逻辑) |
GroundPlaneManager |
地面面片管理器,负责实际的地面显示 |
CommonSkillAreaSelector |
基类,处理暂停/恢复、事件注册 |
FightSkillPutManager |
技能释放UI管理器 |
技能释放类型枚举
文件:Assets/Code/Scripts/GamePlay/Area/Skill/SkillAreaSelector2.cs
public enum ECacheUseType
{
RealUse, // 非暂停时,真正释放
CacheUse, // 暂停时,缓存技能
Cancel, // 取消技能选择
}
完整流程
阶段1:进入技能预览
入口方法:SkillAreaSelector2.EnterPreview(SkillHandle skill)
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)
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
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:解除暂停时释放
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() |
取消选中时隐藏显示 |
显示流程
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
缓存技能的覆盖逻辑
当一个单位已经缓存了技能,玩家再次为该单位选择技能释放位置时,会直接覆盖之前的缓存数据。
覆盖机制
// 使用字典的索引器赋值,如果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
if (isPlayerOperate && unit is UnitCharacter character)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_AUDIO_CLICK_MOVE, character);
}
文件:Assets/Code/Scripts/GamePlay/Level/SkillPauseCache/SkillPauseCacheManager.cs
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
Dictionary<GameUnit, EventDataUseSkill> dicCacheSkill;
EventDataUseSkill
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指令管理(移动指令触发取消缓存) |
注意事项
- 显示时机:只有在暂停状态下选中已缓存技能的单位时才会显示缓存区域
- 自动隐藏:解除暂停时会自动隐藏所有缓存区域显示
- 资源预加载:
skill_inpause_preview_point.prefab在关卡加载时预加载 - 每单位限制:每个单位最多只能缓存一个技能,再次选择会覆盖
- 取消选中:确认技能释放点后会自动取消选中该单位,方便玩家继续操作其他单位
文档生成时间:2026-02-05 生成工具:Cursor AI Agent