update 2.1.30

This commit is contained in:
YHH
2025-08-11 09:31:44 +08:00
parent edc60fc3d8
commit 5bce08683a
14 changed files with 111 additions and 99 deletions

View File

@@ -10,7 +10,7 @@
TypeScript ECS (Entity-Component-System) 框架,专为游戏开发设计。
## 💡 项目特色
## 项目特色
<div align="center">
@@ -61,9 +61,8 @@ class PositionComponent extends Component {
public x: number = 0;
public y: number = 0;
constructor(...args: unknown[]) {
constructor(x: number = 0, y: number = 0) {
super();
const [x = 0, y = 0] = args as [number?, number?];
this.x = x;
this.y = y;
}
@@ -73,9 +72,8 @@ class VelocityComponent extends Component {
public x: number = 0;
public y: number = 0;
constructor(...args: unknown[]) {
constructor(x: number = 0, y: number = 0) {
super();
const [x = 0, y = 0] = args as [number?, number?];
this.x = x;
this.y = y;
}
@@ -116,7 +114,7 @@ Core.update(deltaTime);
```typescript
import { Matcher } from '@esengine/ecs-framework';
// 方式1使用Matcher和EntitySystem
// 使用Matcher和EntitySystem进行高效查询
class QuerySystem extends EntitySystem {
constructor() {
super(Matcher.all(PositionComponent, VelocityComponent).none(HealthComponent));
@@ -128,23 +126,37 @@ class QuerySystem extends EntitySystem {
}
}
// 方式2手动过滤场景中的实体
const results = scene.entities.buffer.filter(entity =>
entity.hasComponent(PositionComponent) &&
entity.hasComponent(VelocityComponent) &&
!entity.hasComponent(HealthComponent)
);
// 更复杂的查询条件
class CombatSystem extends EntitySystem {
constructor() {
super(
Matcher
.all(PositionComponent, HealthComponent) // 必须有位置和血量
.any(WeaponComponent, MagicComponent) // 有武器或魔法
.none(DeadComponent) // 不能是死亡状态
);
}
protected override process(entities: Entity[]) {
// 处理战斗逻辑
}
}
```
### 事件系统
```typescript
import { EventHandler, ECSEventType } from '@esengine/ecs-framework';
import { EventHandler, ECSEventType, IEntityEventData } from '@esengine/ecs-framework';
class GameSystem {
@EventHandler(ECSEventType.ENTITY_DESTROYED)
onEntityDestroyed(data: any) {
console.log('实体销毁:', data.entityName);
onEntityDestroyed(data: IEntityEventData) {
console.log('实体销毁:', data.entityName, '实体ID:', data.entityId);
}
@EventHandler(ECSEventType.ENTITY_CREATED)
onEntityCreated(data: IEntityEventData) {
console.log('实体创建:', data.entityName, '标签:', data.entityTag);
}
}
```
@@ -169,10 +181,10 @@ class OptimizedTransformComponent extends Component {
```
**性能优势**
- 🚀 **缓存友好** - 连续内存访问缓存命中率提升85%
- **批量处理** - 同类型数据处理速度提升2-3倍
- 🔄 **热切换** - 开发期AoS便于调试生产期SoA提升性能
- 🎯 **自动优化** - `@EnableSoA`装饰器自动转换存储结构
- **缓存友好** - 连续内存访问缓存命中率提升85%
- **批量处理** - 同类型数据处理速度提升2-3倍
- **热切换** - 开发期AoS便于调试生产期SoA提升性能
- **自动优化** - `@EnableSoA`装饰器自动转换存储结构
## 平台集成
@@ -185,9 +197,9 @@ update(deltaTime: number) {
```
**专用调试插件**
- 🔧 [ECS 可视化调试插件](https://store.cocos.com/app/detail/7823) - 提供完整的可视化调试界面
- 📊 实体查看器、组件编辑器、系统监控
- 📈 性能分析和实时数据监控
- [ECS 可视化调试插件](https://store.cocos.com/app/detail/7823) - 提供完整的可视化调试界面
- 实体查看器、组件编辑器、系统监控
- 性能分析和实时数据监控
### Laya 引擎
```typescript
@@ -222,16 +234,16 @@ function gameLoop(currentTime: number) {
### 查询 API
```typescript
// Matcher API - 用于EntitySystem
// Matcher API - 推荐方式,高效且类型安全
Matcher.all(...components) // 包含所有组件
Matcher.any(...components) // 包含任意组件
Matcher.none(...components) // 不包含组件
// 手动查询 - 用于场景实体过滤
scene.entities.buffer.filter(entity =>
entity.hasComponent(ComponentA) &&
entity.tag === someTag
);
// 组合查询示例
Matcher
.all(PositionComponent, VelocityComponent) // 必须有这些组件
.any(PlayerComponent, AIComponent) // 其中之一
.none(DeadComponent, DisabledComponent); // 排除这些
```
## 文档

View File

@@ -2,24 +2,24 @@
欢迎使用ECS框架本指南为新手提供了完整的学习路径从基础概念到高级应用帮你快速掌握ECS框架开发游戏。
## 📚 学习路径
## 学习路径
### 第一阶段:基础入门(必读)
#### 1. [快速开始](getting-started.md)
- **5分钟入门** - 创建你的第一个ECS游戏
- 📦 **环境搭建** - 安装和配置框架
- **环境搭建** - 安装和配置框架
- **第一个游戏** - 完整的示例游戏
- **基础API** - 核心功能介绍
#### 2. [核心概念](core-concepts.md)
- 🏗️ **ECS架构** - 实体、组件、系统的关系
- **ECS架构** - 实体、组件、系统的关系
- **API参考** - 核心类和方法
- **最佳实践** - 代码规范和设计模式
- **查询系统** - 如何高效查找实体
#### 3. [概念详解](concepts-explained.md) **新手必读**
- 🤔 **通俗解释** - 用简单语言解释复杂概念
#### 3. [概念详解](concepts-explained.md) **新手必读**
- **通俗解释** - 用简单语言解释复杂概念
- **性能优化技术** - 组件索引、Archetype、脏标记
- **索引选择指南** - 何时使用哈希索引vs位图索引
- **应用场景** - 不同游戏类型的选择建议
@@ -27,39 +27,39 @@
### 第二阶段:核心功能掌握
#### 4. [实体管理指南](entity-guide.md)
- 🎭 **实体基础** - 什么是实体,如何创建和使用
- 🏷️ **标签系统** - 实体分类和查找
- 🔄 **生命周期** - 实体的创建、更新、销毁
- **实体基础** - 什么是实体,如何创建和使用
- **标签系统** - 实体分类和查找
- **生命周期** - 实体的创建、更新、销毁
- **简单示例** - 玩家、敌人、道具实体
#### 5. [组件设计最佳实践](component-design-guide.md) **设计必读**
- 🧩 **组件设计原则** - 单一职责、数据为主
- 📦 **组件类型** - 数据组件、标记组件、行为组件
- 🔗 **组件通信** - 如何让组件协同工作
#### 5. [组件设计最佳实践](component-design-guide.md) **设计必读**
- **组件设计原则** - 单一职责、数据为主
- **组件类型** - 数据组件、标记组件、行为组件
- **组件通信** - 如何让组件协同工作
- **性能优化** - 对象池和数据紧凑性
- 🧪 **测试和调试** - 如何测试你的组件
- **测试和调试** - 如何测试你的组件
#### 6. [系统详解指南](system-guide.md) **逻辑必读**
- ⚙️ **四种系统类型** - EntitySystem、ProcessingSystem、IntervalSystem、PassiveSystem
#### 6. [系统详解指南](system-guide.md) **逻辑必读**
- **四种系统类型** - EntitySystem、ProcessingSystem、IntervalSystem、PassiveSystem
- **使用场景** - 什么时候用哪种系统
- 📋 **执行顺序** - 系统间的依赖关系
- 🔄 **系统通信** - 事件驱动的松耦合设计
- **执行顺序** - 系统间的依赖关系
- **系统通信** - 事件驱动的松耦合设计
- **性能优化** - 批量处理和频率控制
### 第三阶段:高级功能应用
#### 7. [场景管理指南](scene-management-guide.md)
- 🎬 **场景概念** - 什么是场景,如何组织游戏世界
- 🔄 **场景切换** - 菜单、游戏、暂停场景的切换
- 💾 **数据传递** - 场景间如何传递数据
- **场景概念** - 什么是场景,如何组织游戏世界
- **场景切换** - 菜单、游戏、暂停场景的切换
- **数据传递** - 场景间如何传递数据
- **实际应用** - 完整的游戏场景设计
- **性能优化** - 场景级别的性能监控
#### 8. [定时器系统指南](timer-guide.md)
- **定时器基础** - 延迟执行、重复执行
- 🔗 **定时器链** - 顺序执行多个任务
- **定时器基础** - 延迟执行、重复执行
- **定时器链** - 顺序执行多个任务
- **条件定时器** - 等待特定条件满足
- ⏸️ **可暂停定时器** - 游戏暂停功能
- **可暂停定时器** - 游戏暂停功能
- **游戏应用** - Buff系统、技能冷却、关卡限时
#### 9. [查询系统使用](query-system-usage.md)
@@ -69,9 +69,9 @@
- **优化技巧** - 提高查询效率
#### 10. [事件系统示例](event-system-example.md)
- 📡 **事件基础** - 发送和监听事件
- **事件基础** - 发送和监听事件
- **游戏事件** - 玩家输入、碰撞、分数等
- 🔄 **系统解耦** - 用事件实现系统间通信
- **系统解耦** - 用事件实现系统间通信
- **事件统计** - 监控事件系统性能
### 第四阶段:实战应用
@@ -94,12 +94,12 @@
- **基准数据** - 框架性能表现
- **对比分析** - 与其他框架的比较
- **优化建议** - 针对不同规模的优化策略
- 📋 **性能检查清单** - 确保最佳性能的要点
- **性能检查清单** - 确保最佳性能的要点
#### 14. [性能优化技术](performance-optimization.md)
- **核心优化** - 组件索引、Archetype、脏标记
- 💾 **内存优化** - 对象池、数据紧凑性
- 🔄 **批量处理** - 减少单次操作开销
- **内存优化** - 对象池、数据紧凑性
- **批量处理** - 减少单次操作开销
- **监控工具** - 性能分析和调试
## 推荐学习顺序
@@ -125,7 +125,7 @@
→ 4. 性能优化技术 → 5. 实体管理器高级功能
```
## 🤔 常见学习问题
## 常见学习问题
### Q: 我应该从哪里开始?
@@ -175,13 +175,13 @@ A:
- **多做实验** - 尝试不同的设计方案,体会优劣
### 理解原理
- 🤔 **思考为什么** - 不只学怎么做,更要理解为什么这样做
- **思考为什么** - 不只学怎么做,更要理解为什么这样做
- **关注性能** - 了解各种操作的性能影响
- **深入源码** - 有疑问时查看框架源码
### 循序渐进
- 📚 **按顺序学习** - 先掌握基础,再学高级功能
- **按顺序学习** - 先掌握基础,再学高级功能
- **专注重点** - 每次只专注一个主题,不要贪多
- 🔄 **反复练习** - 重要概念要多练习才能熟练
- **反复练习** - 重要概念要多练习才能熟练
开始你的ECS学习之旅吧

View File

@@ -9,7 +9,7 @@
**核心理念:** 组件主要存储数据,复杂逻辑放在系统中处理。
```typescript
// 好的设计:主要是数据
// 好的设计:主要是数据
class HealthComponent extends Component {
public maxHealth: number;
public currentHealth: number;
@@ -56,7 +56,7 @@ class BadHealthComponent extends Component {
每个组件只负责一个方面的数据。
```typescript
// 好的设计:单一职责
// 好的设计:单一职责
class PositionComponent extends Component {
public x: number = 0;
public y: number = 0;
@@ -108,7 +108,7 @@ class TransformComponent extends Component {
使用多个小组件组合,而不是大而全的组件继承。
```typescript
// 好的设计:组合方式
// 好的设计:组合方式
class Player {
constructor(scene: Scene) {
const player = scene.createEntity("Player");
@@ -390,7 +390,7 @@ class InventoryComponent extends Component {
组件间不应直接通信,通过系统或事件系统进行通信。
```typescript
// 好的设计:通过事件通信
// 好的设计:通过事件通信
class HealthComponent extends Component {
public currentHealth: number;
public maxHealth: number;
@@ -555,7 +555,7 @@ class BulletPool {
保持组件数据紧凑,避免不必要的对象分配。
```typescript
// 好的设计:紧凑的数据结构
// 好的设计:紧凑的数据结构
class ParticleComponent extends Component {
// 使用基本类型,避免对象分配
public x: number = 0;

View File

@@ -156,7 +156,7 @@ componentIndex.setIndexType(StateComponent, 'bitmap'); // 状态组件变
| **内存使用** | 较少 | 随实体数增加 |
| **批量操作** | 一般 | 优秀 |
#### 🤔 快速决策流程
#### 快速决策流程
**第一步:判断组件变化频率**
- 组件经常添加/删除? → 选择 **位图索引**
@@ -217,7 +217,7 @@ componentIndex.setIndexType(CombatComponent, 'bitmap'); // 战斗状态临时
const entityCount = 100000;
componentIndex.setIndexType(UnitComponent, 'bitmap'); // 内存占用过大!
// 正确:大量实体用哈希索引
// 正确:大量实体用哈希索引
componentIndex.setIndexType(UnitComponent, 'hash');
```
@@ -226,7 +226,7 @@ componentIndex.setIndexType(UnitComponent, 'hash');
// ❌ 错误Buff频繁添加删除哈希索引效率低
componentIndex.setIndexType(BuffComponent, 'hash'); // 添加删除慢!
// 正确:变化频繁的组件用位图索引
// 正确:变化频繁的组件用位图索引
componentIndex.setIndexType(BuffComponent, 'bitmap');
```
@@ -237,7 +237,7 @@ componentIndex.setIndexType(PositionComponent, 'hash');
componentIndex.setIndexType(BuffComponent, 'hash'); // 应该用bitmap
componentIndex.setIndexType(TemporaryComponent, 'hash'); // 应该用bitmap
// 正确:根据组件特性选择
// 正确:根据组件特性选择
componentIndex.setIndexType(PositionComponent, 'hash'); // 稳定组件
componentIndex.setIndexType(BuffComponent, 'bitmap'); // 变化组件
componentIndex.setIndexType(TemporaryComponent, 'bitmap'); // 临时组件

View File

@@ -2,7 +2,7 @@
本文档详细介绍 ECS Framework 的核心 API 和使用方法。
> 🤔 **不熟悉ECS概念** 建议先阅读 [技术概念详解](concepts-explained.md) 了解ECS架构基础和性能优化原理
> **不熟悉ECS概念** 建议先阅读 [技术概念详解](concepts-explained.md) 了解ECS架构基础和性能优化原理
## ECS 架构概述

View File

@@ -299,7 +299,7 @@ if (entity.isDestroyed) {
# 高级特性请参考其他指南
> 📚 **更多功能:**
> **更多功能:**
> - **高性能查询和批量操作** → [EntityManager 指南](entity-manager-example.md)
> - **性能优化技术** → [性能优化指南](performance-optimization.md)
> - **组件索引和缓存** → [技术概念详解](concepts-explained.md)

View File

@@ -157,7 +157,7 @@ console.log('查询统计:', queryStats);
### 1. 高效查询
```typescript
// 好的做法:缓存查询结果
// 好的做法:缓存查询结果
class CombatSystem extends EntitySystem {
private cachedEnemies: Entity[] = [];
private lastUpdateFrame = 0;
@@ -184,7 +184,7 @@ class CombatSystem extends EntitySystem {
### 2. 批量操作
```typescript
// 好的做法:批量创建和配置
// 好的做法:批量创建和配置
function createBulletWave(count: number): Entity[] {
// 使用Scene的批量创建
const bullets = scene.createEntities(count, "Bullet");
@@ -208,7 +208,7 @@ function createBulletWave(count: number): Entity[] {
### 3. 内存管理
```typescript
// 好的做法:及时清理无用实体
// 好的做法:及时清理无用实体
class CleanupSystem extends EntitySystem {
protected process(entities: Entity[]): void {
// 清理超出边界的子弹
@@ -241,7 +241,7 @@ class CleanupSystem extends EntitySystem {
### 4. 查询优化
```typescript
// 好的做法:使用合适的查询方法
// 好的做法:使用合适的查询方法
class GameSystem extends EntitySystem {
findTargetsInRange(attacker: Entity, range: number): Entity[] {
const attackerPos = attacker.getComponent(PositionComponent);

View File

@@ -16,16 +16,16 @@
### 使用高效的查询方法
```typescript
// 推荐:使用标签查询(快速)
// 推荐:使用标签查询(快速)
const enemies = entityManager.getEntitiesByTag(2);
// 推荐:使用组件查询
// 推荐:使用组件查询
const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
// 推荐使用Scene的查询系统
// 推荐使用Scene的查询系统
const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityComponent);
// ⚠️ 谨慎:自定义条件查询(较慢)
// 谨慎:自定义条件查询(较慢)
const nearbyEnemies = entityManager
.query()
.withAll(PositionComponent)
@@ -68,7 +68,7 @@ class OptimizedCombatSystem extends EntitySystem {
### 批量创建实体
```typescript
// 推荐使用Scene的批量创建
// 推荐使用Scene的批量创建
function createEnemyWave(count: number): Entity[] {
const enemies = scene.createEntities(count, "Enemy");
@@ -144,7 +144,7 @@ class EntityReusableManager {
### 数据局部性优化
```typescript
// 推荐:紧凑的数据结构
// 推荐:紧凑的数据结构
class OptimizedPositionComponent extends Component {
public x: number = 0;
public y: number = 0;

View File

@@ -526,12 +526,12 @@ class InefficientSystem extends EntitySystem {
#### 选择合适的创建方式
```typescript
// 推荐:单一条件使用静态方法
// 推荐:单一条件使用静态方法
const movingEntities = Matcher.all(PositionComponent, VelocityComponent);
const playerEntities = Matcher.byTag(PLAYER_TAG);
const specificEntity = Matcher.byName("Boss");
// 推荐:复杂条件使用链式调用
// 推荐:复杂条件使用链式调用
const complexMatcher = Matcher.empty()
.all(PositionComponent, HealthComponent)
.any(WeaponComponent, MagicComponent)
@@ -554,12 +554,12 @@ const combatUnits = Matcher.all(PositionComponent, HealthComponent)
#### 合理的克隆和重用
```typescript
// 推荐:基础匹配器重用
// 推荐:基础匹配器重用
const livingEntityMatcher = Matcher.all(HealthComponent).none(DeadComponent);
const livingPlayerMatcher = livingEntityMatcher.clone().all(PlayerComponent);
const livingEnemyMatcher = livingEntityMatcher.clone().all(EnemyComponent);
// 推荐:重置匹配器重用
// 推荐:重置匹配器重用
const reusableMatcher = Matcher.empty();
// 用于玩家系统

View File

@@ -8,7 +8,7 @@
场景是一个完整的游戏世界容器,它包含:
- **实体集合** - 所有游戏对象
- ⚙️ **系统集合** - 处理游戏逻辑的系统
- **系统集合** - 处理游戏逻辑的系统
- **事件系统** - 场景内的事件通信
- **查询系统** - 高效的实体查询
- **性能监控** - 场景级别的性能统计

View File

@@ -43,7 +43,7 @@ SoA (Structure of Arrays) 存储模式是ECS框架中的高级性能优化特性
## 适用场景
### 推荐使用SoA的场景
### 推荐使用SoA的场景
1. **大规模实体系统**
```typescript
@@ -203,7 +203,7 @@ class GameComponent extends Component {
### 1. 合理的组件设计
```typescript
// 好的设计:纯数值组件
// 好的设计:纯数值组件
@EnableSoA
class TransformComponent extends Component {
@Float64 public x: number = 0;
@@ -225,7 +225,7 @@ class MixedComponent extends Component {
### 2. 批量操作优化
```typescript
// 使用向量化操作
// 使用向量化操作
const storage = entityManager.getStorage(TransformComponent) as SoAStorage<TransformComponent>;
storage.performVectorizedOperation((fields, indices) => {
const x = fields.get('x') as Float64Array;
@@ -250,7 +250,7 @@ for (const entity of entities) {
### 3. 组件分离策略
```typescript
// 将频繁批量操作的数据分离
// 将频繁批量操作的数据分离
@EnableSoA
class PositionComponent extends Component {
@Float32 public x: number = 0;

View File

@@ -7,9 +7,9 @@
### 什么是定时器?
定时器允许你:
- **延迟执行** - 在指定时间后执行某个操作
- 🔄 **重复执行** - 定期重复执行某个操作
- 🛑 **取消执行** - 在执行前取消定时器
- **延迟执行** - 在指定时间后执行某个操作
- **重复执行** - 定期重复执行某个操作
- **取消执行** - 在执行前取消定时器
- **精确控制** - 精确控制执行时机
### 定时器的优势
@@ -469,7 +469,7 @@ class LevelTimer {
// 时间警告
if (this.timeRemaining === 30) {
console.log("⚠️ 警告还剩30秒");
console.log("警告还剩30秒");
this.playWarningSound();
} else if (this.timeRemaining === 10) {
console.log("🚨 紧急还剩10秒");

2
package-lock.json generated
View File

@@ -11514,7 +11514,7 @@
},
"packages/core": {
"name": "@esengine/ecs-framework",
"version": "2.1.29",
"version": "2.1.30",
"license": "MIT",
"devDependencies": {
"@rollup/plugin-commonjs": "^28.0.3",

View File

@@ -1,6 +1,6 @@
{
"name": "@esengine/ecs-framework",
"version": "2.1.29",
"version": "2.1.30",
"description": "用于Laya、Cocos Creator等JavaScript游戏引擎的高性能ECS框架",
"type": "module",
"main": "bin/index.js",