NLDClient-yudde/ProjectNLD/AI_Gen_Doc/暂停状态下技能释放流程说明.md

13 KiB
Raw Permalink Blame History

暂停状态下技能释放流程说明

本文档由 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
  • PrefabAssets/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指令管理移动指令触发取消缓存

注意事项

  1. 显示时机:只有在暂停状态下选中已缓存技能的单位时才会显示缓存区域
  2. 自动隐藏:解除暂停时会自动隐藏所有缓存区域显示
  3. 资源预加载skill_inpause_preview_point.prefab 在关卡加载时预加载
  4. 每单位限制:每个单位最多只能缓存一个技能,再次选择会覆盖
  5. 取消选中:确认技能释放点后会自动取消选中该单位,方便玩家继续操作其他单位

文档生成时间2026-02-05 生成工具Cursor AI Agent