wiki更新
This commit is contained in:
474
.qoder/repowiki/zh/content/技能执行机制/目标选择策略.md
Normal file
474
.qoder/repowiki/zh/content/技能执行机制/目标选择策略.md
Normal 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. **实时反馈**:提供更直观的目标选择反馈
|
||||
|
||||
该算法为游戏战斗系统提供了坚实的基础,其设计理念和实现方式值得在类似项目中借鉴和应用。
|
||||
Reference in New Issue
Block a user