wiki更新

This commit is contained in:
panw
2025-10-30 16:49:19 +08:00
parent 40e0086be3
commit 93ceaa70e4
18 changed files with 746 additions and 1100 deletions

View File

@@ -0,0 +1,390 @@
# 多段连发技能执行机制深度解析
<cite>
**本文档引用的文件**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts)
- [SkillViewCom.ts](file://assets/script/game/skill/SkillViewCom.ts)
- [AtkConCom.ts](file://assets/script/game/skill/AtkConCom.ts)
- [HeroAttrs.ts](file://assets/script/game/common/config/HeroAttrs.ts)
- [SkillSet.ts](file://assets/script/game/common/config/SkillSet.ts)
</cite>
## 目录
1. [引言](#引言)
2. [WFUNY属性机制概述](#wfuny属性机制概述)
3. [核心组件架构](#核心组件架构)
4. [check_wfuny概率触发机制](#check_wfuny概率触发机制)
5. [递归调度执行模型](#递归调度执行模型)
6. [技能执行链路分析](#技能执行链路分析)
7. [ECS实体生成与管理](#ecs实体生成与管理)
8. [定时器延迟加载机制](#定时器延迟加载机制)
9. [节点有效性检查机制](#节点有效性检查机制)
10. [性能优化与风险控制](#性能优化与风险控制)
11. [总结](#总结)
## 引言
本系统实现了一套基于WFUNY属性的概率性多段技能连发机制通过随机数与英雄属性的比较实现技能触发概率控制配合递归调度和ECS实体管理构建了一个完整的技能执行流水线。该机制不仅支持技能连续释放效果还通过多重验证确保异步执行的安全性。
## WFUNY属性机制概述
WFUNY属性作为系统的核心概率控制因子定义了技能连发的基础触发概率。该属性属于百分比型属性其数值直接影响技能连发的成功概率。
```mermaid
classDiagram
class HeroAttrs {
+WFUNY : number
+check_wfuny() boolean
+calculateAttributeGains() object
}
class SkillConComp {
+check_wfuny() boolean
+castSkill() void
+doSkill() void
-_timers : object
}
class SkillEnt {
+load() void
+destroy() void
}
HeroAttrs --> SkillConComp : "提供WFUNY属性"
SkillConComp --> SkillEnt : "创建技能实体"
```
**图表来源**
- [HeroAttrs.ts](file://assets/script/game/common/config/HeroAttrs.ts#L40-L45)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L95-L104)
**章节来源**
- [HeroAttrs.ts](file://assets/script/game/common/config/HeroAttrs.ts#L40-L45)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L95-L104)
## 核心组件架构
系统采用ECS架构模式主要包含以下核心组件
### 技能控制器组件 (SkillConComp)
负责技能的整体调度和生命周期管理,维护定时器集合和技能状态。
### 技能实体 (SkillEnt)
作为ECS实体封装技能的完整生命周期包括特效加载、参数传递和资源管理。
### 技能视图组件 (SkillViewCom)
处理技能的视觉表现和动画控制,协调技能的执行时机和效果展示。
### 攻击组件 (AtkConCom)
实现具体的伤害计算和碰撞检测逻辑,支持多种攻击模式和伤害类型。
```mermaid
graph TB
subgraph "技能执行流水线"
A[技能触发] --> B[check_wfuny概率检查]
B --> C{是否满足连发条件}
C --> |是| D[scheduleOnce递归调度]
C --> |否| E[doSkill执行]
D --> F[doSkill递归调用]
F --> G[技能实体创建]
G --> H[特效播放]
H --> I[伤害计算]
end
subgraph "ECS实体管理"
J[SkillEnt实体] --> K[SkillViewCom组件]
K --> L[AtkConCom组件]
L --> M[碰撞检测]
end
E --> G
I --> N[目标伤害处理]
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L58-L110)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L13-L77)
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L35)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L1-L33)
## check_wfuny概率触发机制
`check_wfuny`方法实现了基于随机数的概率触发逻辑,这是整个连发机制的核心判断点。
### 概率计算算法
```mermaid
flowchart TD
A[开始check_wfuny] --> B[生成0-100的随机数]
B --> C[获取WFUNY属性值]
C --> D{random < WFUNY?}
D --> |是| E[返回true - 触发连发]
D --> |否| F[返回false - 不触发连发]
E --> G[继续技能连发]
F --> H[结束当前技能]
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L95-L104)
### 实现细节分析
该方法采用简单的概率判断逻辑:
1. 生成0-100范围内的随机浮点数
2. 获取英雄的WFUNY属性值
3. 比较随机数与WFUNY值
4. 当随机数小于WFUNY时返回true否则返回false
这种设计确保了技能连发的概率可控,且与英雄属性紧密关联。
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L95-L104)
## 递归调度执行模型
系统采用`scheduleOnce`方法实现递归调度每次调度间隔为0.1秒,形成稳定的技能连发节奏。
### 调度机制流程
```mermaid
sequenceDiagram
participant SC as SkillConComp
participant Timer as scheduleOnce
participant DS as doSkill
participant SE as SkillEnt
participant SV as SkillViewCom
SC->>SC : castSkill触发
SC->>SC : check_wfuny判断
alt WFUNY触发成功
SC->>Timer : scheduleOnce(doSkill, 0.1)
Timer->>DS : 0.1秒后回调
DS->>SC : 递归调用doSkill
SC->>SE : 创建技能实体
SE->>SV : 初始化技能组件
SV->>SV : 执行技能逻辑
else WFUNY触发失败
SC->>DS : 直接执行doSkill
DS->>SE : 创建技能实体
SE->>SV : 初始化技能组件
SV->>SV : 执行技能逻辑
end
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
### 递归安全机制
系统通过以下机制避免无限递归:
1. **概率控制**WFUNY属性限制了连发的概率
2. **条件检查**:每次递归都进行节点有效性验证
3. **状态管理**通过定时器ID管理和清理机制
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
## 技能执行链路分析
技能执行遵循严格的调用链路,确保各组件间的协调工作。
### 主要执行路径
```mermaid
flowchart LR
A[castSkill] --> B[check_wfuny]
B --> C{WFUNY检查}
C --> |成功| D[doSkill + 递归调度]
C --> |失败| E[doSkill + 直接执行]
D --> F[技能实体创建]
E --> F
F --> G[特效播放]
G --> H[目标选择]
H --> I[伤害计算]
I --> J[效果应用]
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L58-L110)
### 关键执行步骤
1. **技能触发阶段**`castSkill`方法启动技能执行
2. **概率验证阶段**`check_wfuny`验证连发条件
3. **实体创建阶段**通过ECS框架创建技能实体
4. **特效播放阶段**:播放技能视觉效果
5. **目标选择阶段**:根据技能配置选择目标
6. **伤害计算阶段**:计算并应用伤害效果
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L58-L110)
## ECS实体生成与管理
系统采用ECS架构模式通过SkillEnt实体统一管理技能的生命周期。
### 实体创建流程
```mermaid
classDiagram
class SkillEnt {
+load(startPos, parent, uuid, targetPos, caster, dmg) void
+destroy() void
-init() void
}
class SkillViewCom {
+s_uuid : number
+caster : HeroViewComp
+Attrs : object
+doSkill() void
+move() void
}
class AtkConCom {
+single_damage() void
+onBeginContact() void
+update() void
}
SkillEnt --> SkillViewCom : "添加组件"
SkillViewCom --> AtkConCom : "协作处理"
```
**图表来源**
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L13-L77)
- [SkillViewCom.ts](file://assets/script/game/skill/SkillViewCom.ts#L13-L155)
### 实体参数传递
SkillEnt.load方法负责将所有必要的参数传递给技能实体
| 参数 | 类型 | 描述 | 用途 |
|------|------|------|------|
| startPos | Vec3 | 技能起始位置 | 确定技能发射点 |
| parent | Node | 父节点 | 设置技能层级关系 |
| uuid | number | 技能唯一标识 | 查找技能配置 |
| targetPos | any[] | 目标位置数组 | 多目标技能支持 |
| caster | HeroViewComp | 施法者组件 | 获取施法者属性 |
| dmg | number | 伤害值 | 支持伤害倍率计算 |
**章节来源**
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L13-L77)
## 定时器延迟加载机制
系统采用setTimeout实现300毫秒的延迟加载确保技能特效完全播放后再开始执行。
### 延迟加载流程
```mermaid
sequenceDiagram
participant SC as SkillConComp
participant Timer as setTimeout
participant SE as SkillEnt
participant SV as SkillViewCom
SC->>SC : doSkill执行
SC->>SC : playSkillEffect播放特效
SC->>Timer : setTimeout(300ms)
Timer->>SC : 300ms后回调
SC->>SE : ecs.getEntity<SkillEnt>()
SC->>SE : load()加载技能
SE->>SV : 初始化技能组件
SV->>SV : 开始技能逻辑
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
### 定时器管理策略
系统维护一个定时器字典每个技能UUID对应一个定时器ID
```typescript
private _timers: { [key: string]: any } = {};
```
这种设计允许:
- 单独管理每个技能的定时器
- 支持技能中断和清理
- 避免定时器泄漏
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L20-L25)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
## 节点有效性检查机制
为了确保异步执行的安全性,系统在多个关键节点实施有效性检查。
### 检查层次结构
```mermaid
flowchart TD
A[技能开始] --> B{this.node有效?}
B --> |否| C[直接返回]
B --> |是| D{this.HeroView有效?}
D --> |否| C
D --> |是| E{HeroView.node有效?}
E --> |否| C
E --> |是| F[继续执行]
F --> G[技能实体创建]
G --> H{再次检查节点}
H --> |否| I[清理资源]
H --> |是| J[执行技能逻辑]
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L75-L85)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L78-L85)
### 检查时机分布
1. **技能触发前检查**:验证调用者的有效性
2. **定时器回调检查**:确保延迟执行时对象仍然存在
3. **技能实体创建检查**:验证目标节点的有效性
4. **组件更新检查**:防止已销毁对象的访问
这种多层次的检查机制有效防止了内存泄漏和空指针异常。
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L75-L85)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L78-L85)
## 性能优化与风险控制
### 性能优化策略
1. **ECS架构优势**:组件化设计提高内存利用率
2. **延迟加载**300ms延迟避免立即创建大量对象
3. **定时器复用**:统一管理定时器资源
4. **条件检查**:及时退出无效执行路径
### 风险控制机制
1. **概率限制**WFUNY属性控制连发频率
2. **超时保护**0.1秒间隔避免CPU占用过高
3. **内存管理**:自动清理定时器和销毁实体
4. **异常捕获**:节点有效性检查防止崩溃
### 安全边界设计
```mermaid
graph LR
A[输入验证] --> B[概率控制]
B --> C[定时器管理]
C --> D[节点检查]
D --> E[资源清理]
E --> F[异常处理]
```
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L95-L104)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
## 总结
这套基于WFUNY属性的多段技能连发机制展现了现代游戏开发中复杂系统的设计精髓
1. **概率驱动的动态行为**通过WFUNY属性实现技能连发的概率控制使战斗更具策略性和不确定性
2. **异步执行的安全保障**:多重节点有效性检查确保了异步操作的稳定性
3. **ECS架构的高效利用**:组件化设计提供了良好的扩展性和维护性
4. **资源管理的精细化**:定时器管理和实体生命周期控制体现了对性能的关注
5. **递归调度的巧妙运用**0.1秒间隔的递归调度既保证了流畅性,又避免了性能问题
这套机制不仅实现了技能连发功能,更为复杂的技能系统扩展奠定了坚实基础,是游戏开发中概率性技能系统设计的优秀范例。

View File

@@ -0,0 +1,440 @@
# 技能冷却管理系统
<cite>
**本文档引用的文件**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts)
- [SkillSet.ts](file://assets/script/game/common/config/SkillSet.ts)
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts)
- [BoxSet.ts](file://assets/script/game/common/config/BoxSet.ts)
- [HeroAttrs.ts](file://assets/script/game/common/config/HeroAttrs.ts)
</cite>
## 目录
1. [简介](#简介)
2. [系统架构概览](#系统架构概览)
3. [核心组件分析](#核心组件分析)
4. [冷却机制实现](#冷却机制实现)
5. [状态管理与控制流](#状态管理与控制流)
6. [定时器资源管理](#定时器资源管理)
7. [最佳实践指南](#最佳实践指南)
8. [故障排除](#故障排除)
9. [总结](#总结)
## 简介
SkillConComp是游戏技能冷却管理系统的核心组件负责维护和管理角色技能的冷却状态。该系统采用基于update循环的帧累加机制通过精确的时间累积和多重条件判断来实现智能的技能触发逻辑。系统不仅处理技能冷却计算还集成状态检测、资源管理和生命周期控制等功能。
## 系统架构概览
技能冷却管理系统采用分层架构设计,主要由以下层次组成:
```mermaid
graph TB
subgraph "技能冷却系统架构"
A[SkillConComp] --> B[HeroViewComp]
A --> C[SkillSet配置]
A --> D[GameEvent事件]
A --> E[定时器管理]
B --> F[技能列表]
B --> G[状态检测]
B --> H[属性计算]
C --> I[技能配置]
C --> J[冷却参数]
D --> K[战斗结束事件]
D --> L[暂停事件]
E --> M[setTimeout管理]
E --> N[cleanup机制]
end
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L177)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L1-L780)
## 核心组件分析
### SkillConComp组件
SkillConComp是技能冷却管理的主要控制器继承自CCComp基类实现了完整的冷却逻辑和生命周期管理。
#### 主要属性和方法
| 属性/方法 | 类型 | 描述 | 默认值 |
|-----------|------|------|--------|
| HeroView | any | 关联的HeroView组件 | null |
| HeroEntity | any | 关联的实体对象 | null |
| TALCOMP | any | 技能组件 | null |
| skill_cd | number | 全局技能冷却 | 0 |
| _timers | object | 定时器集合 | {} |
#### 生命周期管理
```mermaid
sequenceDiagram
participant Init as 初始化阶段
participant Load as 加载阶段
participant Start as 启动阶段
participant Update as 更新循环
participant Destroy as 销毁阶段
Init->>Load : init()
Load->>Start : onLoad()
Start->>Update : start()
Update->>Update : update(dt)
Update->>Destroy : onDestroy()
Destroy->>Init : clear_timer()
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L20-L35)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L160-L177)
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L177)
### HeroViewComp组件
HeroViewComp作为技能状态的承载者提供了技能列表管理和状态查询功能。
#### 技能状态管理
| 状态属性 | 类型 | 描述 | 用途 |
|----------|------|------|------|
| skills | array | 当前技能列表 | 存储技能配置和冷却状态 |
| mp | number | 当前魔法值 | 冷却触发条件之一 |
| is_atking | boolean | 是否处于攻击状态 | 影响技能触发时机 |
**节来源**
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L80-L90)
## 冷却机制实现
### 帧累加冷却计算
技能冷却采用基于update循环的帧累加机制每帧将deltaTime累加到技能的当前冷却时间上。
#### 冷却计算流程
```mermaid
flowchart TD
Start([update循环开始]) --> CheckState{检查游戏状态}
CheckState --> |非战斗状态| Skip[跳过冷却计算]
CheckState --> |战斗状态| CheckStun{检查眩晕状态}
CheckStun --> |眩晕中| Skip
CheckStun --> |清醒状态| GetSkills[获取技能列表]
GetSkills --> LoopSkills[遍历技能数组]
LoopSkills --> AddDeltaTime[累加dt到cd]
AddDeltaTime --> CheckConditions{检查触发条件}
CheckConditions --> |cd > cd_max且mp充足| TriggerSkill[触发技能]
CheckConditions --> |不满足条件| NextSkill[下一个技能]
TriggerSkill --> ResetCD[重置冷却时间]
ResetCD --> DeductMP[扣除魔法值]
DeductMP --> NextSkill
NextSkill --> MoreSkills{还有更多技能?}
MoreSkills --> |是| LoopSkills
MoreSkills --> |否| End([循环结束])
Skip --> End
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L37-L55)
#### 双重条件判断逻辑
冷却触发采用严格的双重条件判断机制:
1. **冷却时间条件**`skills[i].cd > skills[i].cd_max`
2. **魔法值条件**`this.HeroView.mp >= skills[i].cost`
只有当这两个条件同时满足时,技能才会被触发。
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L42-L50)
### 技能触发机制
#### 触发条件详解
```mermaid
flowchart TD
A[技能触发检查] --> B{cd > cd_max?}
B --> |否| C[继续冷却]
B --> |是| D{mp >= cost?}
D --> |否| C
D --> |是| E{技能类型检查}
E --> |伤害技能| F{is_atking?}
E --> |其他技能| G[直接触发]
F --> |是| H{SType.damage?}
F --> |否| C
H --> |是| I[触发技能]
H --> |否| C
G --> I
I --> J[重置cd=0]
J --> K[扣除mp]
K --> L[播放特效]
L --> M[执行技能逻辑]
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L42-L50)
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L57-L65)
## 状态管理与控制流
### 游戏状态检测
系统通过多个层面的状态检测来决定是否进行冷却计算:
#### 状态检查层次
| 检查层级 | 检查内容 | 实现位置 | 作用 |
|----------|----------|----------|------|
| Mission状态 | `smc.mission.play` | update方法 | 检查整体游戏状态 |
| Pause状态 | `smc.mission.pause` | update方法 | 检查暂停状态 |
| 状态异常 | `this.HeroView.isStun()` | update方法 | 检查眩晕状态 |
| 状态异常 | `this.HeroView.isFrost()` | update方法 | 检查冰冻状态 |
#### 状态检测流程
```mermaid
sequenceDiagram
participant Update as update循环
participant SM as smc.mission
participant HeroView as HeroView
participant Skills as 技能列表
Update->>SM : 检查play状态
SM-->>Update : 返回状态
Update->>SM : 检查pause状态
SM-->>Update : 返回状态
Update->>HeroView : 检查眩晕状态
HeroView-->>Update : 返回状态
Update->>HeroView : 检查冰冻状态
HeroView-->>Update : 返回状态
Update->>Skills : 获取技能列表
Skills-->>Update : 返回技能数组
Update->>Update : 执行冷却计算
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L37-L40)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L465-L470)
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L37-L40)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L465-L470)
### 非战斗状态处理
在非战斗状态下,系统会完全跳过冷却计算,确保资源的有效利用:
#### 非战斗状态判断
```typescript
// 非战斗状态检查逻辑
if(!smc.mission.play || smc.mission.pause) return
```
这种设计避免了在菜单界面、加载画面等非战斗状态下进行不必要的计算开销。
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L37-L40)
## 定时器资源管理
### 定时器生命周期
SkillConComp实现了完整的定时器生命周期管理包括创建、使用和清理三个阶段。
#### 定时器管理架构
```mermaid
graph LR
subgraph "定时器生命周期"
A[创建定时器] --> B[存储到_timers]
B --> C[技能执行]
C --> D[定时器回调]
D --> E[清理定时器]
E --> F[内存释放]
end
subgraph "清理策略"
G[战斗结束] --> H[clear_timer]
I[组件销毁] --> J[onDestroy]
K[手动重置] --> L[reset]
end
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L15-L16)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L155)
#### 定时器清理机制
系统提供了多种定时器清理机制:
| 清理方式 | 触发条件 | 实现方法 | 作用范围 |
|----------|----------|----------|----------|
| 战斗结束清理 | GameEvent.FightEnd | clear_timer() | 所有定时器 |
| 组件销毁清理 | onDestroy() | onDestroy() | 当前组件 |
| 手动重置清理 | reset() | reset() | 当前组件 |
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L155)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L160-L177)
### 资源释放过程
#### 定时器释放流程
```mermaid
sequenceDiagram
participant Event as 战斗结束事件
participant Comp as SkillConComp
participant Timer as 定时器系统
participant Memory as 内存管理
Event->>Comp : GameEvent.FightEnd
Comp->>Comp : clear_timer()
Comp->>Timer : Object.values(_timers).forEach(clearTimeout)
Timer->>Memory : 释放定时器资源
Memory-->>Timer : 确认释放
Timer-->>Comp : 清理完成
Comp->>Comp : _timers = {}
Note over Comp,Memory : 组件销毁时自动清理
Comp->>Comp : onDestroy()
Comp->>Timer : 再次清理所有定时器
Comp->>Comp : 重置_timers对象
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L155)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L160-L177)
**节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
## 最佳实践指南
### 暂停状态下的冷却处理
在游戏暂停状态下,系统会完全跳过冷却计算,这是推荐的最佳实践:
#### 暂停状态处理
```typescript
// 推荐的暂停状态处理
update(dt: number) {
if(!smc.mission.play || smc.mission.pause) return
// 冷却计算逻辑
}
```
这种方式确保了在暂停状态下不会产生额外的计算开销,同时保持了冷却状态的准确性。
### 战斗结束后的清理
战斗结束后必须及时清理定时器资源,避免内存泄漏:
#### 战斗结束清理
```typescript
// 战斗结束事件监听
init(): void {
this.on(GameEvent.FightEnd, this.clear_timer, this);
}
// 清理方法实现
public clear_timer() {
Object.values(this._timers).forEach(clearTimeout);
}
```
### 非play状态的处理
在非战斗状态(如菜单界面)下,系统会自动跳过冷却计算:
#### 非play状态检查
```typescript
// 非play状态检查
if(!smc.mission.play || smc.mission.pause) return
```
这种设计确保了系统只在需要的时候进行计算,提高了整体性能。
## 故障排除
### 常见问题及解决方案
#### 问题1技能冷却不准确
**症状**:技能冷却时间显示不正确
**原因**update循环被中断或dt值异常
**解决方案**
- 检查smc.mission.play状态
- 验证dt参数的有效性
- 确保update方法正常执行
#### 问题2定时器泄漏
**症状**:内存使用持续增长
**原因**:定时器未正确清理
**解决方案**
- 在onDestroy中清理定时器
- 确保GameEvent.FightEnd事件正确触发
- 检查定时器ID的唯一性
#### 问题3技能无法触发
**症状**:技能达到冷却时间但不触发
**原因**:多重条件判断失败
**解决方案**
- 检查mp值是否足够
- 验证is_atking状态
- 确认技能配置正确
### 调试技巧
#### 冷却状态监控
```typescript
// 添加调试日志
update(dt: number) {
console.log(`冷却状态 - play: ${smc.mission.play}, pause: ${smc.mission.pause}`);
console.log(`技能冷却 - 当前mp: ${this.HeroView.mp}`);
}
```
#### 定时器状态检查
```typescript
// 定时器状态监控
public debugTimers() {
console.log('当前定时器:', Object.keys(this._timers));
console.log('定时器数量:', Object.values(this._timers).length);
}
```
## 总结
SkillConComp技能冷却管理系统是一个设计精良的组件具有以下特点
### 核心优势
1. **精确的帧累加机制**基于update循环的冷却计算确保了时间精度
2. **多重条件判断**:双条件触发机制保证了技能使用的合理性
3. **完善的生命周期管理**:从创建到销毁的完整资源管理
4. **灵活的状态控制**:支持各种游戏状态下的冷却处理
### 设计亮点
- **模块化架构**:清晰的职责分离和组件交互
- **资源优化**:智能的状态检查避免不必要的计算
- **错误处理**:完善的异常情况处理机制
- **扩展性**:良好的接口设计支持功能扩展
### 性能考虑
系统通过智能的状态检查和条件判断,有效减少了不必要的计算开销,在保证功能完整性的同时维持了良好的性能表现。
这个技能冷却管理系统为游戏提供了稳定可靠的技能控制机制,是游戏战斗系统的重要组成部分。

View File

@@ -0,0 +1,359 @@
# 技能执行机制
<cite>
**本文档中引用的文件**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts)
- [SkillSet.ts](file://assets/script/game/common/config/SkillSet.ts)
- [SkillViewCom.ts](file://assets/script/game/skill/SkillViewCom.ts)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts)
</cite>
## 目录
1. [概述](#概述)
2. [核心组件架构](#核心组件架构)
3. [技能冷却检测机制](#技能冷却检测机制)
4. [技能施放流程](#技能施放流程)
5. [多段连发技能机制](#多段连发技能机制)
6. [目标选择策略](#目标选择策略)
7. [异常处理与资源清理](#异常处理与资源清理)
8. [性能优化考虑](#性能优化考虑)
9. [最佳实践总结](#最佳实践总结)
## 概述
SkillConComp类是游戏技能控制系统的核心组件负责管理英雄的技能冷却、自动施放条件判断以及技能执行流程。该系统采用ECS架构模式结合定时器机制和节点有效性检查实现了复杂的技能逻辑控制。
## 核心组件架构
```mermaid
classDiagram
class SkillConComp {
+HeroView : HeroViewComp
+HeroEntity : any
+TALCOMP : TalComp
+skill_cd : number
-_timers : object
+init() void
+onLoad() void
+start() void
+update(dt : number) void
+castSkill(config : SkillConfig) void
-doSkill(config : SkillConfig, is_wfuny : boolean, dmg : number) void
+check_wfuny() boolean
+selectTargets(t_num : number) Vec3[]
+clear_timer() void
+reset() void
+onDestroy() void
}
class SkillEnt {
+load(startPos : Vec3, parent : Node, uuid : number, targetPos : any[], caster : HeroViewComp, dmg : number) void
+destroy() void
+init() void
}
class HeroViewComp {
+playSkillEffect(skill_id : number) void
+skills : any[]
+mp : number
+is_atking : boolean
+isStun() boolean
+isFrost() boolean
}
class SkillSet {
+SType : enum
+TGroup : enum
+SkillConfig : interface
}
SkillConComp --> HeroViewComp : "控制"
SkillConComp --> SkillEnt : "创建"
SkillConComp --> SkillSet : "使用配置"
SkillEnt --> SkillViewCom : "包含"
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L17-L177)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L14-L78)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L70-L780)
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L177)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L1-L78)
## 技能冷却检测机制
### update循环中的冷却检测
SkillConComp的update方法实现了精确的技能冷却管理系统
```mermaid
flowchart TD
Start([update循环开始]) --> CheckMission{"检查游戏状态<br/>smc.mission.play && !pause"}
CheckMission --> |否| End([结束])
CheckMission --> |是| CheckStatus{"检查状态<br/>!isStun && !isFrost"}
CheckStatus --> |否| End
CheckStatus --> |是| LoopSkills["遍历技能列表"]
LoopSkills --> AddCD["累积冷却时间<br/>skills[i].cd += dt"]
AddCD --> CheckCD{"冷却完成<br/>cd > cd_max?"}
CheckCD --> |否| NextSkill["下一技能"]
CheckCD --> |是| CheckMP{"检查魔法值<br/>mp >= cost?"}
CheckMP --> |否| NextSkill
CheckMP --> |是| CheckType{"技能类型<br/>SType.damage?"}
CheckType --> |否| NextSkill
CheckType --> |是| CheckAttack{"正在攻击<br/>is_atking?"}
CheckAttack --> |否| NextSkill
CheckAttack --> |是| CastSkill["调用castSkill"]
CastSkill --> ResetCD["重置冷却<br/>skills[i].cd = 0"]
ResetCD --> ConsumeMP["消耗魔法值<br/>mp -= cost"]
ConsumeMP --> NextSkill
NextSkill --> MoreSkills{"还有技能?"}
MoreSkills --> |是| LoopSkills
MoreSkills --> |否| End
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L35-L52)
### 冷却检测的关键要素
1. **时间累积机制**:每个技能的冷却时间通过`skills[i].cd += dt`逐步累积
2. **阈值判断**:当冷却时间超过最大冷却时间`cd_max`时触发
3. **资源检查**:确保魔法值充足`this.HeroView.mp >= skills[i].cost`
4. **状态验证**:排除眩晕和冰冻状态影响
5. **攻击状态检查**:只有在攻击状态下才允许施放伤害技能
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L35-L52)
## 技能施放流程
### castSkill与doSkill方法调用链
```mermaid
sequenceDiagram
participant Player as "玩家输入/自动触发"
participant SkillCon as "SkillConComp"
participant HeroView as "HeroViewComp"
participant SkillEnt as "SkillEnt"
participant ECS as "ECS系统"
Player->>SkillCon : castSkill(config)
SkillCon->>SkillCon : check_wfuny()
SkillCon->>SkillCon : doSkill(config, wfuny, dmg)
Note over SkillCon : 节点有效性检查
SkillCon->>SkillCon : 检查节点有效性
alt 目标组为Self
SkillCon->>SkillCon : targets = [this.node.position]
else 目标组为Enemy
SkillCon->>SkillCon : selectTargets(config.t_num)
end
SkillCon->>HeroView : playSkillEffect(config.uuid)
HeroView->>HeroView : 播放技能特效
SkillCon->>ECS : ecs.getEntity<SkillEnt>(SkillEnt)
SkillCon->>SkillCon : 创建setTimeout定时器
Note over SkillCon : 延迟执行300ms
SkillCon->>SkillCon : 定时器回调函数
SkillCon->>SkillCon : 再次检查节点有效性
SkillCon->>SkillEnt : sEnt.load(...)
SkillCon->>SkillEnt : load方法
SkillEnt->>SkillEnt : 加载技能预制体
SkillEnt->>SkillEnt : 设置节点属性
SkillEnt->>SkillEnt : 添加SkillViewCom组件
alt wfuny机制启用
SkillCon->>SkillCon : scheduleOnce(doSkill, 0.1)
end
Note over SkillCon : 保存定时器ID
SkillCon->>SkillCon : this._timers[`skill_${config.uuid}`] = timerId
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L54-L85)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L15-L77)
### 节点有效性检查机制
系统实现了双重节点有效性检查:
1. **初始检查**:在`doSkill`方法开头进行基础节点有效性验证
2. **延迟检查**:在定时器回调函数中再次确认节点状态
这种设计确保了即使在技能施放过程中节点被销毁,也不会导致错误操作。
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L54-L85)
## 多段连发技能机制
### wfuny机制实现原理
wfuny机制是一种基于概率的技能连发系统
```mermaid
flowchart TD
Start([doSkill开始]) --> CheckWfuny{"检查wfuny<br/>check_wfuny()"}
CheckWfuny --> |false| NormalSkill["正常技能执行"]
CheckWfuny --> |true| ScheduleOnce["scheduleOnce(doSkill, 0.1)"]
ScheduleOnce --> RecursiveCall["递归调用doSkill<br/>is_wfuny=false"]
RecursiveCall --> CheckWfuny2{"再次检查wfuny"}
CheckWfuny2 --> |false| FinalExecution["最终技能执行"]
CheckWfuny2 --> |true| ContinueRecursion["继续递归"]
ContinueRecursion --> ScheduleOnce
NormalSkill --> SaveTimer["保存定时器ID"]
FinalExecution --> SaveTimer
SaveTimer --> End([结束])
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L82-L87)
### wfuny概率计算
```typescript
check_wfuny() {
let random = Math.random() * 100
if (random < this.HeroView.Attrs[Attrs.WFUNY]) {
return true
}
return false
}
```
该方法:
1. 生成0-100之间的随机数
2. 与英雄的WFUNY属性值比较
3. 当随机数小于WFUNY值时返回true触发连发
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L89-L95)
## 目标选择策略
### selectTargets方法实现
```mermaid
flowchart TD
Start([selectTargets开始]) --> GetEntities["获取目标实体<br/>check_target()"]
GetEntities --> CheckEmpty{"实体列表为空?"}
CheckEmpty --> |是| DefaultPos["返回默认位置<br/>t_num个相同坐标"]
DefaultPos --> Return([返回目标坐标数组])
CheckEmpty --> |否| FindFront["找到最前排目标<br/>get_front(entities)"]
FindFront --> PushFront["targets.push(frontPos)"]
PushFront --> LoopOthers["循环处理剩余目标<br/>i=1 to t_num-1"]
LoopOthers --> SelectRandom["随机选择实体<br/>Math.floor(Math.random() * entities.length)"]
SelectRandom --> GetRandomPos["获取随机实体位置"]
GetRandomPos --> PushRandom["targets.push(randomPos)"]
PushRandom --> MoreTargets{"还有目标?"}
MoreTargets --> |是| LoopOthers
MoreTargets --> |否| Return
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L112-L155)
### 目标选择算法详解
1. **实体获取**:通过`check_target()`方法获取敌方实体列表
2. **前排优先**:第一个目标总是最前排的实体
3. **随机分布**:后续目标从所有可用实体中随机选择
4. **重复可能**:由于随机选择,可能出现重复目标
5. **默认处理**:当没有可用目标时,返回预设的默认位置
### 默认位置处理逻辑
```typescript
const defaultPos = this.HeroView.fac === FacSet.HERO ? v3(400, 0, 0) : v3(-400, 0, 0)
```
系统根据施法者阵营确定默认位置:
- 英雄阵营x=400
- 敌人阵营x=-400
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L112-L155)
## 异常处理与资源清理
### 定时器管理机制
```mermaid
classDiagram
class TimerManagement {
-_timers : object
+clear_timer() void
+reset() void
+onDestroy() void
}
class TimerOperations {
+Object.values(this._timers).forEach(clearTimeout)
+this._timers = {}
+this.off(GameEvent.CastHeroSkill)
}
TimerManagement --> TimerOperations : "执行"
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L157-L177)
### 异常处理策略
1. **节点有效性检查**:在关键操作前后检查节点状态
2. **定时器清理**:确保技能执行完成后清理相关定时器
3. **事件监听移除**:在组件销毁时移除事件监听器
4. **资源释放**在组件销毁时释放ECS实体资源
### 资源清理最佳实践
```typescript
public clear_timer() {
Object.values(this._timers).forEach(clearTimeout);
}
reset() {
this.clear_timer();
}
onDestroy() {
Object.values(this._timers).forEach(clearTimeout);
this._timers = {};
this.off(GameEvent.CastHeroSkill);
}
```
这些方法确保:
- 防止内存泄漏
- 避免僵尸定时器
- 清理事件监听器
- 正确释放ECS资源
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L157-L177)
## 性能优化考虑
### 定时器优化策略
1. **延迟执行**技能实体创建延迟300ms避免立即创建大量对象
2. **条件检查**:在每次操作前进行有效性检查,防止无效操作
3. **批量清理**:使用`Object.values`一次性清理所有定时器
### 内存管理优化
1. **及时清理**:在组件销毁时立即清理所有资源
2. **弱引用**:避免循环引用导致的内存泄漏
3. **对象池**利用ECS系统提供的实体池机制
## 最佳实践总结
### 技能系统设计原则
1. **模块化设计**SkillConComp专注于控制逻辑SkillEnt负责实体管理
2. **事件驱动**通过ECS系统实现松耦合的组件通信
3. **容错机制**:多重节点有效性检查确保系统稳定性
4. **资源管理**:完善的定时器和事件监听器清理机制
### 开发建议
1. **扩展性考虑**:为新的技能类型预留接口
2. **性能监控**:定期检查定时器数量和内存使用情况
3. **调试支持**:保留必要的日志输出便于问题排查
4. **测试覆盖**:确保各种边界情况都有相应的测试用例
这个技能执行机制展现了现代游戏开发中复杂系统的设计精髓,通过合理的架构设计和完善的异常处理,实现了稳定可靠的技能控制系统。

View File

@@ -0,0 +1,506 @@
# 技能执行资源管理
<cite>
**本文档中引用的文件**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts)
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts)
- [MissionComp.ts](file://assets/script/game/map/MissionComp.ts)
- [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts)
- [HeroConComp.ts](file://assets/script/game/hero/HeroConComp.ts)
- [timer.md](file://doc/core/common/timer.md)
- [MapView.ts](file://assets/script/game/map/MapView.ts)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构概述](#项目结构概述)
3. [核心组件分析](#核心组件分析)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
在Cocos游戏引擎的战斗系统中技能执行过程中的定时器资源管理是一个关键的系统级问题。本文档深入分析了技能执行过程中定时器资源的创建、存储、清理和生命周期管理策略重点关注`_doSkill`方法中`setTimeout`创建的timerId如何被存储于`_timers`对象中,并通过`clear_timer`方法统一清除的完整流程。
## 项目结构概述
该项目采用基于组件的架构设计,技能系统的核心组件分布在以下目录结构中:
```mermaid
graph TB
subgraph "技能系统架构"
SkillConComp["SkillConComp<br/>技能控制器组件"]
SkillEnt["SkillEnt<br/>技能实体管理"]
HeroViewComp["HeroViewComp<br/>英雄视图组件"]
MissionComp["MissionComp<br/>任务管理组件"]
end
subgraph "事件系统"
GameEvent["GameEvent<br/>游戏事件枚举"]
MessageSystem["消息系统<br/>事件分发"]
end
subgraph "定时器管理"
TimerModule["定时器模块<br/>Oops Framework"]
LocalTimers["_timers对象<br/>本地定时器存储"]
end
SkillConComp --> SkillEnt
SkillConComp --> HeroViewComp
MissionComp --> GameEvent
GameEvent --> MessageSystem
SkillConComp --> LocalTimers
TimerModule --> LocalTimers
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L177)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L1-L78)
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts#L1-L70)
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L50)
- [SkillEnt.ts](file://assets/script/game/skill/SkillEnt.ts#L1-L30)
## 核心组件分析
### SkillConComp - 技能控制器组件
`SkillConComp`是技能系统的核心控制器,负责技能的施放、定时器管理和生命周期控制。该组件维护了一个私有的`_timers`对象用于存储所有技能执行过程中创建的定时器ID。
#### 主要特性:
- **定时器存储管理**:使用`_timers: { [key: string]: any } = {}`对象存储定时器
- **生命周期钩子**:实现了`onDestroy``reset`方法进行资源清理
- **事件监听**:订阅`FightEnd`事件进行自动清理
- **节点有效性检查**:在多个关键点进行节点有效性验证
#### 定时器管理流程:
```mermaid
sequenceDiagram
participant Player as "玩家输入"
participant SkillCon as "SkillConComp"
participant Timer as "setTimeout"
participant TimersObj as "_timers对象"
participant EventSys as "事件系统"
participant Cleanup as "清理机制"
Player->>SkillCon : castSkill()
SkillCon->>SkillCon : doSkill()
SkillCon->>Timer : setTimeout(callback, delay)
Timer-->>SkillCon : timerId
SkillCon->>TimersObj : this._timers[key] = timerId
Note over SkillCon,TimersObj : 定时器创建完成
alt 战斗结束事件触发
EventSys->>SkillCon : FightEnd事件
SkillCon->>Cleanup : clear_timer()
Cleanup->>TimersObj : Object.values(_timers).forEach(clearTimeout)
TimersObj-->>Cleanup : 清理所有定时器
else 组件销毁
SkillCon->>Cleanup : onDestroy()
Cleanup->>TimersObj : Object.values(_timers).forEach(clearTimeout)
Cleanup->>TimersObj : this._timers = {}
end
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L18-L35)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
## 架构概览
技能执行资源管理系统采用多层次的清理策略,确保定时器资源得到妥善管理:
```mermaid
flowchart TD
Start([技能施放开始]) --> ValidateNode["节点有效性检查"]
ValidateNode --> CreateTimer["创建setTimeout定时器"]
CreateTimer --> StoreTimer["存储到_timers对象"]
StoreTimer --> ExecuteSkill["执行技能逻辑"]
ExecuteSkill --> CheckEvent{"战斗结束事件?"}
CheckEvent --> |是| AutoCleanup["自动清理机制"]
CheckEvent --> |否| ContinueExecution["继续执行"]
ContinueExecution --> CheckDestroy{"组件销毁?"}
CheckDestroy --> |是| ManualCleanup["手动清理机制"]
CheckDestroy --> |否| WaitNextFrame["等待下一帧"]
AutoCleanup --> ClearAllTimers["clear_timer()清理所有定时器"]
ManualCleanup --> ClearAllTimers
ClearAllTimers --> ResetTimersObj["重置_timers对象"]
ResetTimersObj --> RemoveListeners["移除事件监听器"]
WaitNextFrame --> CheckEvent
RemoveListeners --> End([资源清理完成])
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
- [MissionComp.ts](file://assets/script/game/map/MissionComp.ts#L80-L95)
## 详细组件分析
### 定时器创建与存储机制
#### doSkill方法中的定时器创建
`doSkill`方法中,技能执行采用了延迟执行模式,通过`setTimeout`创建定时器来延迟技能的实际执行:
```mermaid
classDiagram
class SkillConComp {
-_timers : { [key : string] : any }
+doSkill(config, is_wfuny, dmg)
+clear_timer()
+onDestroy()
+reset()
}
class TimerStorage {
+storeTimer(key, timerId)
+clearAllTimers()
+resetObject()
}
class NodeValidation {
+checkNodeValidity()
+checkHeroViewValidity()
}
SkillConComp --> TimerStorage : "管理"
SkillConComp --> NodeValidation : "验证"
TimerStorage --> NodeValidation : "依赖"
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
#### 定时器存储策略
定时器ID通过键值对形式存储在`_timers`对象中,键名采用`skill_{uuid}`格式,确保唯一性和可追溯性:
| 存储策略 | 优势 | 应用场景 |
|---------|------|----------|
| 键值对存储 | 支持按技能UUID快速查找和清理 | 单个技能的精确清理 |
| 对象引用 | 集合操作支持批量清理 | 批量资源清理 |
| 类型安全 | TypeScript类型约束 | 编译时错误预防 |
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L66-L110)
### 生命周期钩子中的定时器清理
#### onDestroy方法的清理策略
`onDestroy`方法实现了组件销毁时的资源清理,这是防止内存泄漏的最后一道防线:
```mermaid
flowchart LR
OnDestroy[onDestroy触发] --> ClearTimers["Object.values(_timers).forEach(clearTimeout)"]
ClearTimers --> ResetObject["this._timers = {}"]
ResetObject --> RemoveListeners["this.off(GameEvent.CastHeroSkill)"]
RemoveListeners --> Complete[清理完成]
subgraph "清理保护机制"
SafetyCheck["节点有效性检查"]
NullCheck["空值检查"]
TypeGuard["类型守卫"]
end
ClearTimers -.-> SafetyCheck
ClearTimers -.-> NullCheck
ClearTimers -.-> TypeGuard
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
#### reset方法的资源重置
`reset`方法提供了组件重置时的资源清理功能,主要用于组件池化场景:
| 清理阶段 | 操作内容 | 目的 |
|---------|----------|------|
| 定时器清理 | 调用`clear_timer()`方法 | 防止定时器残留 |
| 状态重置 | 重置内部状态变量 | 准备组件复用 |
| 事件解绑 | 解除事件监听器 | 避免内存泄漏 |
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L140-L150)
### FightEnd事件监听机制
#### 战斗结束自动清理触发路径
战斗结束时的自动清理通过事件驱动机制实现,确保所有技能定时器得到及时清理:
```mermaid
sequenceDiagram
participant Hero as "英雄死亡"
participant MissionComp as "MissionComp"
participant MessageSys as "消息系统"
participant SkillCon as "SkillConComp"
participant TimerMgr as "定时器管理器"
Hero->>MissionComp : do_hero_dead()
MissionComp->>MissionComp : 检查英雄数量
alt 英雄全部死亡
MissionComp->>MessageSys : dispatchEvent(FightEnd)
MessageSys->>SkillCon : 触发FightEnd事件
SkillCon->>TimerMgr : clear_timer()
TimerMgr->>TimerMgr : 清理所有定时器
end
```
**图表来源**
- [MissionComp.ts](file://assets/script/game/map/MissionComp.ts#L55-L65)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L20-L25)
#### 事件监听器的注册与管理
`init`方法中注册了`FightEnd`事件监听器,确保战斗结束时能够触发自动清理:
| 监听器类型 | 事件名称 | 回调函数 | 清理时机 |
|-----------|----------|----------|----------|
| 单次监听 | FightEnd | clear_timer | 战斗结束时 |
| 生命周期监听 | onDestroy | 清理所有定时器 | 组件销毁时 |
| 事件解绑 | CastHeroSkill | 移除特定事件监听 | 组件销毁时 |
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L20-L25)
- [MissionComp.ts](file://assets/script/game/map/MissionComp.ts#L55-L65)
### 异常场景下的安全性检查
#### 节点有效性检查实践
在技能执行的关键路径上,实施了多层节点有效性检查,防止因节点被提前销毁而导致的异常:
```mermaid
flowchart TD
EnterMethod[进入方法] --> FirstCheck["首次节点检查"]
FirstCheck --> IsValid1{"节点有效?"}
IsValid1 --> |否| EarlyReturn["提前返回"]
IsValid1 --> |是| ExecuteLogic["执行业务逻辑"]
ExecuteLogic --> SecondCheck["二次节点检查"]
SecondCheck --> IsValid2{"节点仍然有效?"}
IsValid2 --> |否| SafeExit["安全退出"]
IsValid2 --> |是| ContinueExecution["继续执行"]
ContinueExecution --> ThirdCheck["英雄视图检查"]
ThirdCheck --> IsValid3{"英雄视图有效?"}
IsValid3 --> |否| GracefulFail["优雅失败"]
IsValid3 --> |是| FinalExecution["最终执行"]
EarlyReturn --> End[方法结束]
SafeExit --> End
GracefulFail --> End
FinalExecution --> End
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L70-L75)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L80-L85)
#### 异常处理策略
| 异常类型 | 检查点 | 处理策略 | 预防措施 |
|---------|--------|----------|----------|
| 节点被销毁 | 每次关键操作前 | 提前返回,避免操作 | 定期检查节点有效性 |
| 英雄视图丢失 | 技能执行前 | 日志记录,跳过执行 | 保持对英雄状态的监控 |
| 定时器失效 | 定时器回调中 | 检查上下文有效性 | 使用闭包保护上下文 |
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L70-L75)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L80-L85)
## 依赖关系分析
### 组件间依赖关系
技能执行资源管理系统涉及多个组件间的复杂依赖关系:
```mermaid
graph TB
subgraph "核心组件"
SkillConComp["SkillConComp<br/>技能控制器"]
SkillEnt["SkillEnt<br/>技能实体"]
HeroViewComp["HeroViewComp<br/>英雄视图"]
end
subgraph "事件系统"
GameEvent["GameEvent<br/>事件枚举"]
MessageSystem["消息系统"]
end
subgraph "资源管理"
TimerModule["定时器模块"]
ComponentPool["组件池"]
end
subgraph "战斗系统"
MissionComp["MissionComp<br/>任务管理"]
BattleManager["战斗管理器"]
end
SkillConComp --> SkillEnt
SkillConComp --> HeroViewComp
SkillConComp --> TimerModule
SkillConComp --> GameEvent
GameEvent --> MessageSystem
MessageSystem --> SkillConComp
MissionComp --> BattleManager
BattleManager --> MessageSystem
SkillConComp -.-> ComponentPool
HeroViewComp -.-> ComponentPool
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L15)
- [MissionComp.ts](file://assets/script/game/map/MissionComp.ts#L1-L20)
### 外部依赖分析
| 依赖类型 | 组件名称 | 作用 | 影响范围 |
|---------|----------|------|----------|
| 框架依赖 | Oops Framework | 定时器管理、消息系统 | 全局功能 |
| 引擎依赖 | Cocos Creator | 节点管理、组件系统 | 渲染层 |
| 配置依赖 | SkillSet | 技能配置数据 | 业务逻辑 |
| 事件依赖 | GameEvent | 事件通信机制 | 系统集成 |
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L15)
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts#L1-L70)
## 性能考量
### 定时器性能优化
技能系统的定时器管理采用了多项性能优化策略:
#### 定时器池化管理
- **批量清理**:使用`Object.values().forEach()`进行批量定时器清理
- **内存复用**:通过`_timers`对象实现定时器ID的集中管理
- **延迟清理**:在合适的时机(如`onDestroy``FightEnd`事件)进行清理
#### 性能监控指标
| 性能指标 | 目标值 | 监控方法 | 优化策略 |
|---------|--------|----------|----------|
| 定时器数量 | < 100个 | 运行时统计 | 实施清理阈值 |
| 清理耗时 | < 16ms | 时间测量 | 异步清理 |
| 内存占用 | < 10MB | 内存分析 | 对象池化 |
### 内存泄漏防护
系统通过多重防护机制防止内存泄漏:
```mermaid
flowchart LR
subgraph "防护层次"
Level1["第一层:节点检查"]
Level2["第二层:事件解绑"]
Level3["第三层:组件销毁"]
Level4["第四层:框架清理"]
end
Level1 --> Level2
Level2 --> Level3
Level3 --> Level4
subgraph "检测机制"
LeakDetection["泄漏检测"]
MemoryProfiling["内存分析"]
ResourceTracking["资源追踪"]
end
Level4 --> LeakDetection
LeakDetection --> MemoryProfiling
MemoryProfiling --> ResourceTracking
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
## 故障排除指南
### 常见问题诊断
#### 定时器未清理问题
**症状表现**
- 浏览器内存持续增长
- 控制台出现定时器警告
- 技能执行异常延迟
**诊断步骤**
1. 检查`_timers`对象是否正确初始化
2. 验证`onDestroy`方法是否被调用
3. 确认`FightEnd`事件是否正常触发
**解决方案**
```typescript
// 修复方案示例
public onDestroy() {
// 确保清理所有定时器
Object.values(this._timers).forEach(clearTimeout);
this._timers = {};
// 移除事件监听器
this.off(GameEvent.FightEnd);
// 调用父类销毁方法
super.onDestroy();
}
```
#### 节点无效异常
**症状表现**
- 技能执行过程中抛出null引用异常
- 控制台出现"node is not valid"错误
**诊断方法**
- 在关键位置添加节点有效性检查
- 监控节点销毁时机
- 分析组件生命周期
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L70-L75)
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L80-L85)
### 调试工具和技巧
#### 定时器状态监控
开发环境下可以通过以下方式监控定时器状态:
| 监控项 | 检查方法 | 正常状态 | 异常状态 |
|-------|----------|----------|----------|
| 定时器数量 | `Object.keys(this._timers).length` | < 10 | > 100 |
| 清理完整性 | `this._timers`对象状态 | `{}` | 包含未清理的定时器ID |
| 事件监听器 | `this.has(GameEvent.FightEnd)` | `false` | `true` |
#### 性能分析工具
推荐使用以下工具进行性能分析:
- Chrome DevTools Memory面板
- Cocos Creator Profiler
- 自定义定时器监控日志
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L150-L177)
## 结论
技能执行资源管理系统通过多层次的定时器管理策略,实现了高效、安全的资源控制。系统的核心优势包括:
### 主要成就
1. **完善的生命周期管理**:通过`onDestroy``reset`方法确保组件销毁时的资源清理
2. **事件驱动的自动清理**:利用`FightEnd`事件实现战斗结束时的自动资源回收
3. **多重安全性检查**:在关键路径实施节点有效性检查,防止异常情况
4. **灵活的清理策略**:支持单个定时器清理和批量清理两种模式
### 最佳实践总结
- **及时清理**:在组件销毁和战斗结束时立即清理定时器
- **安全性优先**:在每次关键操作前进行节点有效性检查
- **事件驱动**:利用事件系统实现自动化资源管理
- **异常处理**:在定时器回调中实施完善的异常处理机制
### 未来改进方向
1. **异步清理优化**:考虑将大量定时器的清理操作异步化
2. **资源使用统计**:增加定时器使用情况的统计和分析功能
3. **自动泄漏检测**:实现定时器泄漏的自动检测和报告机制
4. **性能监控增强**:集成更详细的性能监控和告警系统
通过这套完整的技能执行资源管理策略,系统能够在保证功能完整性的同时,有效防止内存泄漏和资源浪费,为游戏的稳定运行提供坚实保障。

View File

@@ -0,0 +1,474 @@
# 目标选择策略
<cite>
**本文档引用的文件**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts)
- [BoxSet.ts](file://assets/script/game/common/config/BoxSet.ts)
- [HeroViewComp.ts](file://assets/script/hero/HeroViewComp.ts)
- [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts)
- [heroSet.ts](file://assets/script/game/common/config/heroSet.ts)
- [Hero.ts](file://assets/script/hero/Hero.ts)
- [Mon.ts](file://assets/script/hero/Mon.ts)
</cite>
## 目录
1. [概述](#概述)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 概述
本文档深入分析了《英雄传说》游戏中目标选择算法的核心实现,重点关注`selectTargets`方法的策略设计。该算法采用智能的目标分配机制,确保战斗系统的公平性和策略性。
目标选择算法的核心特点:
- **优先级策略**:第一个目标总是最前排的单位
- **随机性机制**:后续目标通过随机选择确保多样性
- **重复允许**:支持同一目标被多次选中
- **边界处理**:当无可用目标时返回默认位置
- **阵营感知**基于FacSet判断左右方向
## 项目结构
```mermaid
graph TB
subgraph "技能系统"
SkillConComp["SkillConComp<br/>技能控制器"]
SkillEnt["SkillEnt<br/>技能实体"]
end
subgraph "阵营系统"
FacSet["FacSet<br/>阵营枚举"]
HeroViewComp["HeroViewComp<br/>英雄视图组件"]
end
subgraph "ECS系统"
ECS["ECS框架"]
BattleMoveSystem["BattleMoveSystem<br/>战斗移动系统"]
end
subgraph "目标检测"
check_target["check_target()<br/>目标检测"]
get_front["get_front()<br/>前排检测"]
selectTargets["selectTargets()<br/>目标选择"]
end
SkillConComp --> check_target
SkillConComp --> get_front
SkillConComp --> selectTargets
check_target --> ECS
get_front --> ECS
BattleMoveSystem --> ECS
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L109-L122)
- [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L165-L200)
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L177)
- [BoxSet.ts](file://assets/script/game/common/config/BoxSet.ts#L1-L109)
## 核心组件
### SkillConComp - 技能控制器
`SkillConComp`是目标选择算法的核心控制器,负责协调整个目标选择流程。该组件继承自`CCComp`实现了ECS注册功能。
主要职责:
- **技能施放管理**:控制技能的触发时机和目标选择
- **目标选择协调**:调用`selectTargets`方法获取目标坐标
- **异常处理**:确保节点有效性检查和资源清理
### FacSet - 阵营系统
`FacSet`定义了游戏中的阵营概念,是目标选择算法的重要输入参数。
阵营常量:
- `HERO = 0`:英雄阵营,位于战场左侧
- `MON = 1`:怪物阵营,位于战场右侧
阵营决定了目标选择的方向性逻辑,英雄会选择右侧的怪物作为目标,而怪物会选择左侧的英雄作为目标。
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L50)
- [BoxSet.ts](file://assets/script/game/common/config/BoxSet.ts#L48-L50)
## 架构概览
```mermaid
sequenceDiagram
participant SkillCon as "SkillConComp"
participant ECS as "ECS查询系统"
participant BattleMove as "BattleMoveSystem"
participant HeroView as "HeroViewComp"
SkillCon->>SkillCon : check_target()
SkillCon->>ECS : ecs.query(allOf(MonModelComp))
ECS-->>SkillCon : 目标实体列表
alt 有可用目标
SkillCon->>SkillCon : get_front(entities)
SkillCon->>SkillCon : selectTargets(t_num)
SkillCon->>SkillCon : 返回目标坐标数组
else 无可用目标
SkillCon->>SkillCon : 返回默认位置
end
Note over SkillCon,BattleMove : 目标选择完成,准备施放技能
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L109-L154)
- [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L198-L235)
## 详细组件分析
### selectTargets 方法详解
`selectTargets`方法是目标选择算法的核心实现,采用了精心设计的策略来确保战斗的公平性和策略性。
#### 算法流程
```mermaid
flowchart TD
Start([开始目标选择]) --> CheckEntities["检查可用实体"]
CheckEntities --> HasEntities{"是否有可用实体?"}
HasEntities --> |否| DefaultPos["返回默认位置"]
DefaultPos --> CloneDefault["克隆默认位置"]
CloneDefault --> ReturnDefault["返回t_num个默认位置"]
HasEntities --> |是| GetFront["获取最前排目标"]
GetFront --> PushFront["添加最前排坐标到targets"]
PushFront --> LoopTargets["循环添加后续目标"]
LoopTargets --> RandomSelect["随机选择实体"]
RandomSelect --> AddRandom["添加随机坐标到targets"]
AddRandom --> MoreTargets{"还有更多目标?"}
MoreTargets --> |是| LoopTargets
MoreTargets --> |否| ReturnTargets["返回目标坐标数组"]
ReturnDefault --> End([结束])
ReturnTargets --> End
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L128-L154)
#### 第一个目标:最前排单位
算法的第一个目标总是最前排的单位,这是基于以下设计原则:
1. **战略优先级**:最前排单位通常是敌方的主力或关键目标
2. **视觉反馈**:玩家能够直观看到技能的主要目标
3. **战斗节奏**:确保技能施放具有明确的战略意义
**实现细节**
- 使用`get_front`方法确定最前排位置
- 根据阵营方向选择最小或最大X坐标
- 确保第一个目标始终是最接近施法者的前排单位
#### 后续目标:随机选择机制
从第二个目标开始,算法采用随机选择机制:
1. **随机性保证**:每个目标都有平等的选择机会
2. **重复允许**:同一个实体可能被多次选中
3. **性能优化**:避免复杂的排序和去重操作
**实现原理**
- 使用`Math.random()`生成随机索引
- 直接从实体列表中选择对应实体
- 确保算法复杂度为O(n)其中n为目标数量
#### 默认位置处理
当没有可用目标时,算法返回预定义的默认位置:
```typescript
const defaultPos = this.HeroView.fac === FacSet.HERO ? v3(400, 0, 0) : v3(-400, 0, 0);
```
**设计意图**
- **战场定位**:默认位置位于战场边缘,不影响战斗区域
- **视觉平衡**:确保技能效果在视觉上仍然有意义
- **战术灵活性**:为玩家提供策略选择的空间
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L128-L154)
### check_target 方法分析
`check_target`方法负责根据阵营确定目标实体集合:
```mermaid
classDiagram
class SkillConComp {
+HeroView : any
+check_target() Entity[]
+get_front(entities) Vec3
+selectTargets(t_num) Vec3[]
}
class FacSet {
<<enumeration>>
HERO = 0
MON = 1
}
class ECS {
+query(filter) Entity[]
+allOf(component) Filter
}
SkillConComp --> FacSet : "使用"
SkillConComp --> ECS : "查询"
note for SkillConComp "根据阵营决定查询英雄还是怪物"
note for FacSet "定义阵营常量"
note for ECS "提供实体查询功能"
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L109-L115)
- [BoxSet.ts](file://assets/script/game/common/config/BoxSet.ts#L48-L50)
**实现逻辑**
- 英雄阵营FacSet.HERO查询怪物实体MonModelComp
- 怪物阵营FacSet.MON查询英雄实体HeroModelComp
这种设计确保了目标选择的阵营对立性,符合游戏的战斗机制。
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L109-L115)
### get_front 方法详解
`get_front`方法实现了前排单位的智能识别:
#### X坐标比较逻辑
```mermaid
flowchart LR
subgraph "英雄阵营 (FacSet.HERO)"
MinX["Math.min(...entities.map(e => e.get(HeroViewComp).node.position.x))"]
MinX --> Leftmost["找到最左侧的X坐标"]
end
subgraph "怪物阵营 (FacSet.MON)"
MaxX["Math.max(...entities.map(e => e.get(HeroViewComp).node.position.x))"]
MaxX --> Rightmost["找到最右侧的X坐标"]
end
Leftmost --> KeyEntity["查找对应实体"]
Rightmost --> KeyEntity
KeyEntity --> FrontPos["返回前排坐标"]
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L116-L122)
#### 方向性判断
算法根据阵营自动判断左右方向:
1. **英雄阵营**寻找最小X坐标即最左侧的单位
2. **怪物阵营**寻找最大X坐标即最右侧的单位
这种设计符合战场布局的直觉认知,英雄在左侧,怪物在右侧。
#### 实体匹配过程
```typescript
let keyPos = this.HeroView.fac == FacSet.HERO ?
Math.min(...entities.map(e => e.get(HeroViewComp).node.position.x)) :
Math.max(...entities.map(e => e.get(HeroViewComp).node.position.x));
let keyEntity = entities.find(e => e.get(HeroViewComp).node.position.x === keyPos);
return keyEntity.get(HeroViewComp).node.position;
```
这个过程确保了:
- 正确的前排单位被识别
- 坐标信息准确返回
- 异常情况下的稳定性
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L116-L122)
### ECS查询与坐标比较整合
目标选择算法与ECS系统的深度集成体现在以下几个方面
#### 查询优化
```mermaid
graph TD
A[ECS查询] --> B[allOf过滤]
B --> C[实体列表]
C --> D[坐标提取]
D --> E[X坐标数组]
E --> F[Math.min/max计算]
F --> G[前排坐标]
G --> H[实体匹配]
H --> I[最终目标]
style A fill:#e1f5fe
style F fill:#f3e5f5
style I fill:#e8f5e8
```
**图表来源**
- [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L198-L235)
#### 性能考量
1. **批量查询**:一次性获取所有符合条件的实体
2. **延迟计算**:只在需要时进行坐标比较
3. **内存优化**:避免不必要的对象创建
#### 异常处理
算法包含了多层异常保护:
1. **空实体检查**:防止空列表访问
2. **坐标有效性验证**:确保坐标数据正确
3. **实体状态检查**:排除无效或死亡的实体
**章节来源**
- [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L198-L235)
## 依赖关系分析
```mermaid
graph LR
subgraph "外部依赖"
ECS["ECS框架"]
Vec3["Vec3类"]
FacSet["FacSet枚举"]
end
subgraph "内部组件"
SkillConComp["SkillConComp"]
HeroViewComp["HeroViewComp"]
BattleMoveSystem["BattleMoveSystem"]
end
subgraph "配置文件"
BoxSet["BoxSet.ts"]
heroSet["heroSet.ts"]
end
SkillConComp --> ECS
SkillConComp --> Vec3
SkillConComp --> FacSet
SkillConComp --> HeroViewComp
BattleMoveSystem --> ECS
BattleMoveSystem --> HeroViewComp
BoxSet --> FacSet
heroSet --> HeroViewComp
style SkillConComp fill:#ffeb3b
style ECS fill:#2196f3
style FacSet fill:#4caf50
```
**图表来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L15)
- [BoxSet.ts](file://assets/script/game/common/config/BoxSet.ts#L1-L10)
### 核心依赖关系
1. **ECS框架依赖**`ecs.query()`用于实体查询
2. **数学运算依赖**`Math.min()``Math.max()`用于坐标比较
3. **类型系统依赖**`Vec3``Entity`类型定义
4. **配置系统依赖**`FacSet`提供阵营常量
### 松耦合设计
算法采用松耦合设计,便于维护和扩展:
- **接口隔离**通过ECS查询接口与具体实体解耦
- **配置驱动**:阵营逻辑通过配置文件管理
- **模块化组织**:各功能模块职责单一
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L1-L177)
- [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L1-L270)
## 性能考虑
### 时间复杂度分析
目标选择算法的时间复杂度为O(n)其中n为目标数量
1. **ECS查询**O(m)m为实体总数
2. **坐标提取**O(m)
3. **前排计算**O(m)
4. **目标生成**O(n)
### 空间复杂度分析
空间复杂度为O(m+n),主要用于存储实体列表和目标坐标:
1. **实体缓存**:存储查询结果
2. **目标数组**:存储最终目标坐标
3. **临时变量**:坐标计算过程中的中间值
### 性能优化策略
1. **查询复用**:一次查询结果供多个目标选择使用
2. **延迟计算**:只在需要时进行坐标比较
3. **内存池化**重用Vec3对象减少GC压力
## 故障排除指南
### 常见异常情况
#### 空实体列表
**问题描述**:当没有可用目标时,算法返回默认位置。
**解决方案**
- 检查ECS查询条件是否正确
- 验证实体是否正确添加到场景中
- 确认实体组件是否完整
#### 坐标计算错误
**问题描述**:前排单位识别不准确。
**解决方案**
- 验证`HeroViewComp`组件是否正确挂载
- 检查实体位置是否正确初始化
- 确认坐标系统的一致性
#### 随机选择偏差
**问题描述**:随机选择结果不均匀。
**解决方案**
- 检查`Math.random()`的分布特性
- 验证实体列表的完整性
- 确认索引计算的正确性
### 调试技巧
1. **日志记录**:在关键步骤添加调试信息
2. **可视化**:绘制目标选择路径
3. **单元测试**:为每个方法编写测试用例
**章节来源**
- [SkillConComp.ts](file://assets/script/game/hero/SkillConComp.ts#L128-L154)
## 结论
目标选择算法展现了优秀的工程设计原则:
### 设计优势
1. **清晰的职责分离**:每个方法专注于特定功能
2. **灵活的扩展性**:易于适应新的需求变化
3. **稳定的性能表现**O(n)时间复杂度确保高效运行
4. **健壮的异常处理**:多层次保护机制
### 战术价值
算法的设计充分考虑了战斗策略的需求:
- **优先级策略**:确保关键目标优先被选中
- **随机性机制**:增加战斗的不确定性和趣味性
- **边界处理**:优雅处理异常情况
- **阵营感知**:符合游戏世界的逻辑设定
### 未来改进方向
1. **智能预测**:基于历史数据预测目标偏好
2. **动态权重**:根据战斗状态调整目标选择权重
3. **机器学习**利用AI技术优化目标选择策略
4. **实时反馈**:提供更直观的目标选择反馈
该算法为游戏战斗系统提供了坚实的基础,其设计理念和实现方式值得在类似项目中借鉴和应用。