docs: 更新项目文档 - 添加EntityManager、事件系统、性能优化使用示例和说明
This commit is contained in:
429
README.md
429
README.md
@@ -3,18 +3,17 @@
|
||||
[](https://badge.fury.io/js/%40esengine%2Fecs-framework)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
一个轻量级的 TypeScript ECS(Entity-Component-System)框架,专为小游戏开发设计,适用于 Laya、Cocos 等游戏引擎。
|
||||
一个专业级的 TypeScript ECS(Entity-Component-System)框架,采用现代化架构设计,专为高性能游戏开发打造。
|
||||
|
||||
## ✨ 特性
|
||||
## ✨ 核心特性
|
||||
|
||||
- 🚀 **轻量级 ECS 架构** - 基于实体组件系统,提供清晰的代码结构
|
||||
- ⚡ **高性能** - 实体创建速度可达64万实体/秒,支持大规模实体管理
|
||||
- 🎯 **智能优化** - 组件对象池、位掩码优化器、延迟索引更新等性能优化技术
|
||||
- 📡 **事件系统** - 内置 Emitter 事件发射器,支持类型安全的事件管理
|
||||
- ⏰ **定时器系统** - 完整的定时器管理,支持延迟和重复任务
|
||||
- 🔍 **查询系统** - 基于位掩码的高性能实体查询,支持批量操作
|
||||
- 🛠️ **性能监控** - 内置性能监控工具,帮助优化游戏性能
|
||||
- 🔧 **批量操作** - 支持批量实体创建、组件添加等高效操作
|
||||
- 🏗️ **现代化 ECS 架构** - 完整的实体组件系统,提供清晰的代码结构
|
||||
- 📡 **类型安全事件系统** - 增强的事件总线,支持异步事件、优先级、批处理和装饰器
|
||||
- ⏰ **定时器管理系统** - 完整的定时器管理,支持延迟和重复任务
|
||||
- 🔍 **智能查询系统** - 支持复杂的实体查询,流式API设计
|
||||
- ⚡ **高性能优化** - 组件索引、Archetype系统、脏标记机制三重优化
|
||||
- 🛠️ **开发者友好** - 完整的TypeScript支持,丰富的调试工具
|
||||
- 📦 **轻量级设计** - 最小化依赖,适用于各种游戏引擎
|
||||
|
||||
## 📦 安装
|
||||
|
||||
@@ -22,162 +21,194 @@
|
||||
npm install @esengine/ecs-framework
|
||||
```
|
||||
|
||||
## 📊 性能基准
|
||||
|
||||
```bash
|
||||
# 运行快速性能基准测试
|
||||
npm run benchmark
|
||||
|
||||
# 运行完整性能测试
|
||||
npm run test:performance
|
||||
```
|
||||
|
||||
**框架性能数据**:
|
||||
|
||||
### 🚀 实体创建性能
|
||||
- **小规模**: 640,697 实体/秒 (1,000个实体/1.56ms)
|
||||
- **中规模**: 250,345 实体/秒 (10,000个实体/39.94ms)
|
||||
- **大规模**: 161,990 实体/秒 (500,000个实体/3.09秒)
|
||||
|
||||
### 🎯 核心操作性能
|
||||
```
|
||||
📊 核心操作性能
|
||||
实体创建: 640,697个/秒
|
||||
组件添加: 596,929组件/秒
|
||||
位掩码操作: 5,000,000次/秒
|
||||
查询缓存: 零延迟访问
|
||||
批量操作: 高效处理
|
||||
|
||||
🔧 优化技术效果
|
||||
组件对象池: 减少30-50%内存分配
|
||||
位掩码优化器: 提升20-40%掩码性能
|
||||
批量操作: 大幅减少创建时间
|
||||
索引优化: 避免O(n)重复检查
|
||||
缓存策略: 延迟清理机制
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 初始化框架
|
||||
### 1. 基础设置
|
||||
|
||||
```typescript
|
||||
import { Core, CoreEvents } from '@esengine/ecs-framework';
|
||||
import { Core, CoreEvents, Scene } from '@esengine/ecs-framework';
|
||||
|
||||
// 创建 Core 实例
|
||||
const core = Core.create(true); // true 表示开启调试模式
|
||||
const core = Core.create(true); // 开启调试模式
|
||||
|
||||
// 创建场景
|
||||
class GameScene extends Scene {
|
||||
public initialize() {
|
||||
// 场景初始化逻辑
|
||||
}
|
||||
}
|
||||
|
||||
// 在游戏循环中更新框架
|
||||
function gameLoop() {
|
||||
// 发送帧更新事件
|
||||
Core.emitter.emit(CoreEvents.frameUpdated);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 高性能批量创建实体
|
||||
### 2. 创建实体和组件
|
||||
|
||||
```typescript
|
||||
import { Scene, EntitySystem } from '@esengine/ecs-framework';
|
||||
import { Component, Entity } from '@esengine/ecs-framework';
|
||||
|
||||
class GameScene extends Scene {
|
||||
public initialize() {
|
||||
// 批量创建实体
|
||||
const entities = this.createEntities(1000, "Enemy");
|
||||
|
||||
// 批量添加组件
|
||||
entities.forEach((entity, index) => {
|
||||
entity.addComponent(new PositionComponent(
|
||||
Math.random() * 1000,
|
||||
Math.random() * 1000
|
||||
));
|
||||
entity.addComponent(new VelocityComponent());
|
||||
});
|
||||
|
||||
// 添加系统
|
||||
this.addEntityProcessor(new MovementSystem());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 使用组件对象池优化内存
|
||||
|
||||
```typescript
|
||||
import { Component, ComponentPoolManager } from '@esengine/ecs-framework';
|
||||
|
||||
class BulletComponent extends Component {
|
||||
public damage: number = 10;
|
||||
public speed: number = 300;
|
||||
|
||||
// 重置方法用于对象池
|
||||
public reset() {
|
||||
this.damage = 10;
|
||||
this.speed = 300;
|
||||
// 定义组件
|
||||
class PositionComponent extends Component {
|
||||
constructor(public x: number = 0, public y: number = 0) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
// 注册组件池
|
||||
ComponentPoolManager.getInstance().registerPool(BulletComponent, 1000);
|
||||
class VelocityComponent extends Component {
|
||||
constructor(public dx: number = 0, public dy: number = 0) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
// 使用对象池获取组件
|
||||
const bullet = ComponentPoolManager.getInstance().getComponent(BulletComponent);
|
||||
entity.addComponent(bullet);
|
||||
|
||||
// 释放回对象池
|
||||
ComponentPoolManager.getInstance().releaseComponent(bullet);
|
||||
// 创建实体
|
||||
const entity = scene.createEntity("Player");
|
||||
entity.addComponent(new PositionComponent(100, 100));
|
||||
entity.addComponent(new VelocityComponent(10, 0));
|
||||
```
|
||||
|
||||
### 4. 位掩码优化器加速查询
|
||||
### 3. 创建处理系统
|
||||
|
||||
```typescript
|
||||
import { BitMaskOptimizer } from '@esengine/ecs-framework';
|
||||
import { EntitySystem } from '@esengine/ecs-framework';
|
||||
|
||||
// 注册常用组件类型
|
||||
const optimizer = BitMaskOptimizer.getInstance();
|
||||
optimizer.registerComponentType(PositionComponent);
|
||||
optimizer.registerComponentType(VelocityComponent);
|
||||
optimizer.registerComponentType(RenderComponent);
|
||||
class MovementSystem extends EntitySystem {
|
||||
public process(entities: Entity[]) {
|
||||
for (const entity of entities) {
|
||||
const position = entity.getComponent(PositionComponent);
|
||||
const velocity = entity.getComponent(VelocityComponent);
|
||||
|
||||
if (position && velocity) {
|
||||
position.x += velocity.dx;
|
||||
position.y += velocity.dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 预计算常用掩码组合
|
||||
optimizer.precomputeCommonMasks();
|
||||
|
||||
// 高效的掩码操作
|
||||
const positionMask = optimizer.getComponentMask(PositionComponent);
|
||||
const movementMask = optimizer.getCombinedMask([PositionComponent, VelocityComponent]);
|
||||
// 添加系统到场景
|
||||
scene.addEntityProcessor(new MovementSystem());
|
||||
```
|
||||
|
||||
### 4. 实体查询和管理
|
||||
|
||||
```typescript
|
||||
import { EntityManager } from '@esengine/ecs-framework';
|
||||
|
||||
// 使用EntityManager进行高级查询
|
||||
const entityManager = new EntityManager();
|
||||
|
||||
// 查询具有特定组件的实体
|
||||
const movingEntities = entityManager
|
||||
.query()
|
||||
.withAll(PositionComponent, VelocityComponent)
|
||||
.execute();
|
||||
|
||||
// 查询带标签的实体
|
||||
const enemies = entityManager.getEntitiesByTag(1);
|
||||
|
||||
// 批量创建实体
|
||||
const bullets = entityManager.createEntities(100, "bullet");
|
||||
```
|
||||
|
||||
### 5. 事件系统
|
||||
|
||||
```typescript
|
||||
import { EventBus, ECSEventType, EventHandler } from '@esengine/ecs-framework';
|
||||
|
||||
// 获取事件总线
|
||||
const eventBus = entityManager.eventBus;
|
||||
|
||||
// 监听实体创建事件
|
||||
eventBus.onEntityCreated((data) => {
|
||||
console.log(`Entity created: ${data.entityName}`);
|
||||
});
|
||||
|
||||
// 监听组件添加事件
|
||||
eventBus.onComponentAdded((data) => {
|
||||
console.log(`Component ${data.componentType} added to entity ${data.entityId}`);
|
||||
});
|
||||
|
||||
// 使用装饰器自动注册事件监听器
|
||||
class GameManager {
|
||||
@EventHandler(ECSEventType.ENTITY_DESTROYED)
|
||||
onEntityDestroyed(data) {
|
||||
console.log('Entity destroyed:', data.entityName);
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义事件
|
||||
eventBus.emit('player:levelup', { playerId: 123, newLevel: 5 });
|
||||
```
|
||||
|
||||
## 🆚 框架对比
|
||||
|
||||
与其他 TypeScript ECS 框架相比,我们的优势:
|
||||
|
||||
| 特性 | @esengine/ecs-framework | bitecs | ecsy | Miniplex |
|
||||
|------|-------------------------|-------|------|----------|
|
||||
| **TypeScript 支持** | ✅ 原生支持 | ✅ 完整支持 | ⚠️ 部分支持 | ✅ 原生支持 |
|
||||
| **事件系统** | ✅ 类型安全+装饰器 | ❌ 无内置事件系统 | ⚠️ 基础事件 | ✅ 响应式事件 |
|
||||
| **查询系统** | ✅ 智能查询+流式API | ✅ 高性能 | ✅ 基础查询 | ✅ 响应式查询 |
|
||||
| **性能优化** | ✅ 多层优化系统 | ✅ WASM优化 | ⚠️ 基础优化 | ✅ React集成优化 |
|
||||
| **实体管理器** | ✅ 统一管理接口 | ❌ 无统一接口 | ✅ 基础管理 | ✅ 响应式管理 |
|
||||
| **组件索引** | ✅ 哈希+位图索引 | ✅ 原生支持 | ❌ 无索引系统 | ✅ 自动索引 |
|
||||
| **Archetype系统** | ✅ 内置支持 | ✅ 内置支持 | ❌ 无Archetype | ❌ 无Archetype |
|
||||
| **脏标记系统** | ✅ 细粒度追踪 | ⚠️ 基础支持 | ❌ 无脏标记 | ✅ React级追踪 |
|
||||
| **批量操作** | ✅ 全面的批量API | ✅ 批量支持 | ⚠️ 有限支持 | ⚠️ 有限支持 |
|
||||
| **游戏引擎集成** | ✅ 通用设计 | ✅ 通用设计 | ✅ 通用设计 | ⚠️ 主要针对React |
|
||||
| **学习曲线** | 🟢 中等 | 🟡 较陡峭 | 🟢 简单 | 🟡 需要React知识 |
|
||||
| **社区生态** | 🟡 成长中 | 🟢 活跃 | 🟡 稳定 | 🟡 小众但精品 |
|
||||
|
||||
### 为什么选择我们?
|
||||
|
||||
**相比 bitecs**:
|
||||
- 更友好的 TypeScript API,无需手动管理内存
|
||||
- 完整的实体管理器,开发体验更佳
|
||||
- 内置类型安全事件系统,bitecs需要自己实现
|
||||
- 多种索引系统可选,适应不同场景
|
||||
|
||||
**相比 ecsy**:
|
||||
- 现代化的性能优化系统(组件索引、Archetype、脏标记)
|
||||
- 更完整的 TypeScript 类型定义
|
||||
- 增强的事件系统,支持装饰器和异步事件
|
||||
- 活跃的维护和功能更新
|
||||
|
||||
**相比 Miniplex**:
|
||||
- 不依赖 React 生态,可用于任何游戏引擎
|
||||
- 专门针对游戏开发优化
|
||||
- 更轻量级的核心设计
|
||||
- 传统事件模式,更适合游戏开发习惯
|
||||
|
||||
## 📚 核心概念
|
||||
|
||||
### Entity(实体)
|
||||
实体是游戏世界中的基本对象,支持批量操作和高性能创建。
|
||||
实体是游戏世界中的基本对象,可以挂载组件和运行系统。
|
||||
|
||||
```typescript
|
||||
// 单个实体创建
|
||||
const entity = scene.createEntity("MyEntity");
|
||||
// 创建实体
|
||||
const entity = scene.createEntity("Player");
|
||||
|
||||
// 批量实体创建
|
||||
const entities = scene.createEntities(1000, "Bullets");
|
||||
|
||||
// 实体属性设置
|
||||
// 设置实体属性
|
||||
entity.tag = 1;
|
||||
entity.updateOrder = 0;
|
||||
entity.enabled = true;
|
||||
|
||||
// 批量创建实体
|
||||
const entities = scene.createEntities(100, "Enemy");
|
||||
```
|
||||
|
||||
### Component(组件)
|
||||
组件包含数据和行为,支持对象池优化。
|
||||
组件存储数据,定义实体的属性和状态。
|
||||
|
||||
```typescript
|
||||
import { Component, ComponentPoolManager } from '@esengine/ecs-framework';
|
||||
import { Component } from '@esengine/ecs-framework';
|
||||
|
||||
class HealthComponent extends Component {
|
||||
public maxHealth: number = 100;
|
||||
public currentHealth: number = 100;
|
||||
|
||||
// 对象池重置方法
|
||||
public reset() {
|
||||
this.maxHealth = 100;
|
||||
this.currentHealth = 100;
|
||||
}
|
||||
|
||||
public takeDamage(damage: number) {
|
||||
this.currentHealth = Math.max(0, this.currentHealth - damage);
|
||||
if (this.currentHealth <= 0) {
|
||||
@@ -186,30 +217,22 @@ class HealthComponent extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
// 注册到对象池
|
||||
ComponentPoolManager.getInstance().registerPool(HealthComponent, 500);
|
||||
// 添加组件到实体
|
||||
entity.addComponent(new HealthComponent());
|
||||
```
|
||||
|
||||
### System(系统)
|
||||
系统处理实体集合,支持批量处理优化。
|
||||
系统处理具有特定组件的实体集合,实现游戏逻辑。
|
||||
|
||||
```typescript
|
||||
import { EntitySystem, Entity } from '@esengine/ecs-framework';
|
||||
|
||||
class HealthSystem extends EntitySystem {
|
||||
protected process(entities: Entity[]) {
|
||||
// 批量处理实体
|
||||
const batchSize = 1000;
|
||||
for (let i = 0; i < entities.length; i += batchSize) {
|
||||
const batch = entities.slice(i, i + batchSize);
|
||||
this.processBatch(batch);
|
||||
}
|
||||
}
|
||||
|
||||
private processBatch(entities: Entity[]) {
|
||||
for (const entity of entities) {
|
||||
const health = entity.getComponent(HealthComponent);
|
||||
if (health && health.currentHealth <= 0) {
|
||||
// 处理实体死亡逻辑
|
||||
entity.destroy();
|
||||
}
|
||||
}
|
||||
@@ -217,130 +240,22 @@ class HealthSystem extends EntitySystem {
|
||||
}
|
||||
```
|
||||
|
||||
## 🎮 高级功能
|
||||
|
||||
### 批量操作API
|
||||
|
||||
```typescript
|
||||
// 批量创建实体
|
||||
const entities = scene.createEntities(5000, "Enemies");
|
||||
|
||||
// 批量查询
|
||||
const movingEntities = scene.getEntitiesWithComponents([PositionComponent, VelocityComponent]);
|
||||
|
||||
// 延迟缓存清理
|
||||
scene.addEntity(entity, false); // 延迟缓存清理
|
||||
// ... 添加更多实体
|
||||
scene.querySystem.clearCache(); // 手动清理缓存
|
||||
```
|
||||
|
||||
### 性能监控
|
||||
|
||||
```typescript
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
|
||||
// 获取性能统计
|
||||
const stats = scene.getPerformanceStats();
|
||||
console.log(`实体数量: ${stats.entityCount}`);
|
||||
console.log(`查询缓存大小: ${stats.queryCacheSize}`);
|
||||
console.log(`组件池统计:`, stats.componentPoolStats);
|
||||
```
|
||||
|
||||
### 内存优化
|
||||
|
||||
```typescript
|
||||
// 预热组件池
|
||||
ComponentPoolManager.getInstance().preWarmPools({
|
||||
BulletComponent: 1000,
|
||||
EffectComponent: 500,
|
||||
PickupComponent: 200
|
||||
});
|
||||
|
||||
// 清理未使用的组件
|
||||
ComponentPoolManager.getInstance().clearUnusedComponents();
|
||||
```
|
||||
|
||||
## 🧪 测试和基准
|
||||
|
||||
### 运行测试套件
|
||||
## 🧪 测试
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
npm run test
|
||||
|
||||
# 单元测试
|
||||
npm run test:unit
|
||||
|
||||
# 性能测试
|
||||
npm run test:performance
|
||||
|
||||
# 快速基准测试
|
||||
# 性能基准测试
|
||||
npm run benchmark
|
||||
```
|
||||
|
||||
### 自定义性能测试
|
||||
|
||||
```typescript
|
||||
import { runEntityCreationBenchmark } from './Testing/Performance/benchmark';
|
||||
|
||||
// 运行自定义基准测试
|
||||
await runEntityCreationBenchmark();
|
||||
```
|
||||
|
||||
## 🔧 优化建议
|
||||
|
||||
### 大规模实体处理
|
||||
|
||||
1. **使用批量API**
|
||||
```typescript
|
||||
// ✅ 推荐:批量创建
|
||||
const entities = scene.createEntities(10000, "Units");
|
||||
|
||||
// ❌ 避免:循环单个创建
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
scene.createEntity("Unit" + i);
|
||||
}
|
||||
```
|
||||
|
||||
2. **启用对象池**
|
||||
```typescript
|
||||
// 预先注册常用组件池
|
||||
ComponentPoolManager.getInstance().registerPool(BulletComponent, 2000);
|
||||
ComponentPoolManager.getInstance().registerPool(EffectComponent, 1000);
|
||||
```
|
||||
|
||||
3. **优化查询频率**
|
||||
```typescript
|
||||
// 缓存查询结果
|
||||
if (frameCount % 5 === 0) {
|
||||
this.cachedEnemies = scene.getEntitiesWithComponent(EnemyComponent);
|
||||
}
|
||||
```
|
||||
|
||||
### 移动端优化
|
||||
|
||||
- 实体数量建议 ≤ 20,000
|
||||
- 启用组件对象池
|
||||
- 减少查询频率
|
||||
- 使用批量操作
|
||||
|
||||
## 📈 版本更新
|
||||
|
||||
### v2.0.6 (最新)
|
||||
- 🚀 **高性能实体创建**: 支持64万实体/秒的创建速度
|
||||
- 🎯 **组件对象池**: 减少内存分配开销
|
||||
- ⚡ **位掩码优化器**: 加速组件查询和操作
|
||||
- 🔧 **批量操作API**: 支持高效的批量实体创建
|
||||
- 📊 **性能监控**: 完整的性能分析工具
|
||||
- 🧪 **测试套件**: 单元测试、性能测试、集成测试
|
||||
|
||||
### 历史版本
|
||||
- v1.x.x: 基础ECS架构实现
|
||||
|
||||
## 📖 文档
|
||||
|
||||
- [快速入门](docs/getting-started.md) - 从零开始学习框架使用
|
||||
- [实体使用指南](docs/entity-guide.md) - 详细了解实体的所有功能和用法
|
||||
- [EntityManager 使用指南](docs/entity-manager-example.md) - 详细了解实体管理器的高级功能
|
||||
- [事件系统使用指南](docs/event-system-example.md) - 学习类型安全事件系统的完整用法
|
||||
- [性能优化指南](docs/performance-optimization.md) - 深入了解三大性能优化系统
|
||||
- [核心概念](docs/core-concepts.md) - 深入了解 ECS 架构和设计原理
|
||||
- [查询系统使用指南](docs/query-system-usage.md) - 学习高性能查询系统的详细用法
|
||||
|
||||
@@ -380,6 +295,32 @@ cd source && npm install && npm run build
|
||||
|
||||
加入 QQ 群讨论:[ecs游戏框架交流](https://jq.qq.com/?_wv=1027&k=29w1Nud6)
|
||||
|
||||
### 🚀 核心性能指标
|
||||
|
||||
```bash
|
||||
实体创建: 640,000+ 个/秒
|
||||
组件查询: O(1) 复杂度(使用索引)
|
||||
内存优化: 30-50% 减少分配
|
||||
批量操作: 显著提升处理效率
|
||||
```
|
||||
|
||||
### 🎯 性能优化技术
|
||||
|
||||
- **组件索引系统**: 哈希和位图双重索引,支持 O(1) 查询
|
||||
- **Archetype 系统**: 按组件组合分组,减少查询开销
|
||||
- **脏标记机制**: 细粒度变更追踪,避免不必要的计算
|
||||
- **批量操作 API**: 减少函数调用开销,提升大规模操作效率
|
||||
- **智能缓存**: 查询结果缓存和延迟清理机制
|
||||
|
||||
### 🔧 性能建议
|
||||
|
||||
1. **大规模场景**: 使用批量API和组件索引
|
||||
2. **频繁查询**: 启用Archetype系统进行快速筛选
|
||||
3. **实时游戏**: 利用脏标记减少无效更新
|
||||
4. **移动端**: 建议实体数量控制在20,000以内
|
||||
|
||||
运行 `npm run benchmark` 查看在您的环境中的具体性能表现。
|
||||
|
||||
---
|
||||
|
||||
**ECS Framework** - 让游戏开发更简单、更高效!
|
||||
Reference in New Issue
Block a user