新增wasm以优化实体update速度

This commit is contained in:
YHH
2025-06-08 21:50:50 +08:00
parent 0aa4791cf7
commit 8d0ad6b871
51 changed files with 5811 additions and 10773 deletions

View File

@@ -17,7 +17,7 @@ Core 是框架的核心管理类,负责游戏的生命周期管理。
### 创建和配置
```typescript
import { Core } from './Core';
import { Core } from '@esengine/ecs-framework';
// 创建核心实例(调试模式)
const core = Core.create(true);
@@ -29,7 +29,7 @@ const core = Core.create(false);
### 事件系统
```typescript
import { CoreEvents } from './ECS/CoreEvents';
import { CoreEvents } from '@esengine/ecs-framework';
// 监听核心事件
Core.emitter.addObserver(CoreEvents.frameUpdated, this.onUpdate, this);
@@ -62,7 +62,7 @@ Core.schedule(1.0, true, this, (timer) => {
### 创建和使用场景
```typescript
import { Scene } from './ECS/Scene';
import { Scene } from '@esengine/ecs-framework';
// 创建场景
const scene = new Scene();
@@ -77,6 +77,23 @@ scene.update(); // 更新场景
scene.end(); // 结束场景
```
### 批量实体管理
```typescript
// 批量创建实体 - 高性能
const entities = scene.createEntities(1000, "Enemy");
// 批量添加实体(延迟缓存清理)
entities.forEach(entity => {
scene.addEntity(entity, false); // 延迟清理
});
scene.querySystem.clearCache(); // 手动清理缓存
// 获取性能统计
const stats = scene.getPerformanceStats();
console.log(`实体数量: ${stats.entityCount}`);
```
## Entity实体
实体是游戏世界中的基本对象,包含位置、旋转、缩放等基本属性。
@@ -84,7 +101,7 @@ scene.end(); // 结束场景
### 实体的基本属性
```typescript
import { Vector2 } from './Math/Vector2';
import { Vector2 } from '@esengine/ecs-framework';
const entity = scene.createEntity("MyEntity");
@@ -161,7 +178,7 @@ console.log(debugInfo);
### 创建组件
```typescript
import { Component } from './ECS/Component';
import { Component } from '@esengine/ecs-framework';
class HealthComponent extends Component {
public maxHealth: number = 100;
@@ -244,6 +261,43 @@ entity.removeComponentByType(HealthComponent);
entity.removeAllComponents();
```
### 组件对象池优化
```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;
}
}
// 注册组件池
ComponentPoolManager.getInstance().registerPool(BulletComponent, 1000);
// 使用对象池获取组件
const bullet = ComponentPoolManager.getInstance().getComponent(BulletComponent);
entity.addComponent(bullet);
// 释放组件回对象池
ComponentPoolManager.getInstance().releaseComponent(bullet);
// 预热组件池
ComponentPoolManager.getInstance().preWarmPools({
BulletComponent: 1000,
EffectComponent: 500
});
// 获取池统计
const stats = ComponentPoolManager.getInstance().getPoolStats();
console.log('组件池统计:', stats);
```
## Scene场景
场景是实体和系统的容器,管理游戏世界的状态。
@@ -483,14 +537,86 @@ bulletPool.clear();
- 监控性能数据
- 合理使用时间缩放
## 高级性能优化功能
### 位掩码优化器
位掩码优化器可以预计算和缓存常用的组件掩码,提升查询性能。
```typescript
import { BitMaskOptimizer } from '@esengine/ecs-framework';
const optimizer = BitMaskOptimizer.getInstance();
// 注册组件类型
optimizer.registerComponentType(PositionComponent);
optimizer.registerComponentType(VelocityComponent);
optimizer.registerComponentType(RenderComponent);
// 预计算常用掩码组合
optimizer.precomputeCommonMasks();
// 获取优化的掩码
const positionMask = optimizer.getComponentMask(PositionComponent);
const movementMask = optimizer.getCombinedMask([PositionComponent, VelocityComponent]);
// 掩码操作
const hasBothComponents = optimizer.hasAllComponents(entityMask, movementMask);
const hasAnyComponent = optimizer.hasAnyComponent(entityMask, movementMask);
// 获取掩码分析
const analysis = optimizer.analyzeMask(entityMask);
console.log('掩码包含的组件类型:', analysis.componentTypes);
```
### 延迟索引更新器
批量更新索引可以显著提升大规模实体操作的性能。
```typescript
import { IndexUpdateBatcher } from '@esengine/ecs-framework';
const batcher = new IndexUpdateBatcher((updates) => {
// 处理批量更新
console.log(`批量处理 ${updates.length} 个索引更新`);
});
// 配置批量大小和延迟
batcher.configure(100, 16); // 批量大小100延迟16ms
// 添加更新任务
batcher.addUpdate("add", entity, componentMask);
batcher.addUpdate("remove", entity, componentMask);
// 强制刷新
batcher.flush();
```
### 批量操作API
```typescript
// 批量创建实体 - 最高性能
const entities = scene.createEntities(10000, "Bullets");
// 延迟缓存清理
entities.forEach(entity => {
scene.addEntity(entity, false); // 延迟清理
});
scene.querySystem.clearCache(); // 手动清理
// 批量查询优化
const movingEntities = scene.getEntitiesWithComponents([PositionComponent, VelocityComponent]);
```
## 总结
ECS Framework 提供了完整的实体组件系统架构:
- **Core** 管理游戏生命周期和全局功能
- **Entity** 作为游戏对象的基础容器
- **Component** 实现具体的功能模块
- **Component** 实现具体的功能模块,支持对象池优化
- **System** 处理游戏逻辑
- **Scene** 管理游戏世界状态
- **Scene** 管理游戏世界状态,支持批量操作
- **高级优化** 位掩码优化器、组件对象池、批量操作等
通过合理使用这些核心概念,可以构建出结构清晰、易于维护的游戏代码。
通过合理使用这些核心概念和优化功能,可以构建出高性能、结构清晰、易于维护的游戏代码。

View File

@@ -29,6 +29,23 @@ console.log(entity.name); // "Player"
console.log(entity.id); // 唯一的数字ID
```
### 批量创建实体(推荐)
```typescript
import { Scene } from '@esengine/ecs-framework';
const scene = new Scene();
// 批量创建1000个实体 - 高性能
const entities = scene.createEntities(1000, "Enemy");
// 批量配置
entities.forEach((entity, index) => {
entity.tag = 2; // 敌人标签
// 添加组件...
});
```
### 使用流式API创建
```typescript

View File

@@ -9,15 +9,21 @@ ecs-framework/
├── source/
│ ├── src/ # 源代码
│ │ ├── ECS/ # ECS核心系统
│ │ ├── Math/ # 数学运算
│ │ ├── Types/ # 类型定义
│ │ ── Utils/ # 工具类
│ │ ── Utils/ # 工具类
│ │ └── Testing/ # 测试文件
│ ├── scripts/ # 构建脚本
│ └── tsconfig.json # TypeScript配置
└── docs/ # 文档
```
## 安装和构建
## 安装和使用
### NPM 安装
```bash
npm install @esengine/ecs-framework
```
### 从源码构建
@@ -28,27 +34,28 @@ git clone https://github.com/esengine/ecs-framework.git
# 进入源码目录
cd ecs-framework/source
# 安装依赖
npm install
# 编译TypeScript
npx tsc
npm run build
```
### 直接使用
您可以直接将源码复制到项目中使用或者引用编译后的JavaScript文件。
## 基础设置
### 1. 导入框架
```typescript
// 导入核心类
import { Core } from './Core';
import { Entity } from './ECS/Entity';
import { Component } from './ECS/Component';
import { Scene } from './ECS/Scene';
import { QuerySystem } from './ECS/Core/QuerySystem';
import { Emitter } from './Utils/Emitter';
import { TimerManager } from './Utils/Timers/TimerManager';
import {
Core,
Entity,
Component,
Scene,
EntitySystem,
ComponentPoolManager,
BitMaskOptimizer
} from '@esengine/ecs-framework';
```
### 2. 创建基础管理器
@@ -57,9 +64,6 @@ import { TimerManager } from './Utils/Timers/TimerManager';
class GameManager {
private core: Core;
private scene: Scene;
private querySystem: QuerySystem;
private emitter: Emitter;
private timerManager: TimerManager;
constructor() {
// 创建核心实例
@@ -69,21 +73,30 @@ class GameManager {
this.scene = new Scene();
this.scene.name = "GameScene";
// 获取场景的查询系统
this.querySystem = this.scene.querySystem;
// 获取核心的事件系统和定时器
this.emitter = Core.emitter;
this.timerManager = this.core._timerManager;
// 设置当前场景
Core.scene = this.scene;
// 初始化优化功能
this.setupOptimizations();
}
private setupOptimizations() {
// 注册组件对象池
ComponentPoolManager.getInstance().preWarmPools({
PositionComponent: 1000,
VelocityComponent: 1000,
HealthComponent: 500
});
// 注册位掩码优化
const optimizer = BitMaskOptimizer.getInstance();
optimizer.registerComponentType(PositionComponent);
optimizer.registerComponentType(VelocityComponent);
optimizer.registerComponentType(HealthComponent);
optimizer.precomputeCommonMasks();
}
public update(deltaTime: number): void {
// 更新定时器
this.timerManager.update(deltaTime);
// 更新场景
this.scene.update();
@@ -122,6 +135,8 @@ gameLoop();
### 1. 定义组件
```typescript
import { Component, ComponentPoolManager } from '@esengine/ecs-framework';
// 位置组件
class PositionComponent extends Component {
public x: number = 0;
@@ -132,6 +147,12 @@ class PositionComponent extends Component {
this.x = x;
this.y = y;
}
// 对象池重置方法
public reset() {
this.x = 0;
this.y = 0;
}
}
// 速度组件
@@ -144,6 +165,11 @@ class VelocityComponent extends Component {
this.x = x;
this.y = y;
}
public reset() {
this.x = 0;
this.y = 0;
}
}
// 生命值组件
@@ -157,6 +183,11 @@ class HealthComponent extends Component {
this.currentHealth = maxHealth;
}
public reset() {
this.maxHealth = 100;
this.currentHealth = 100;
}
public takeDamage(damage: number): void {
this.currentHealth = Math.max(0, this.currentHealth - damage);
}
@@ -169,6 +200,11 @@ class HealthComponent extends Component {
return this.currentHealth <= 0;
}
}
// 注册组件到对象池
ComponentPoolManager.getInstance().registerPool(PositionComponent, 1000);
ComponentPoolManager.getInstance().registerPool(VelocityComponent, 1000);
ComponentPoolManager.getInstance().registerPool(HealthComponent, 500);
```
### 2. 创建实体
@@ -180,10 +216,19 @@ class GameManager {
public createPlayer(): Entity {
const player = this.scene.createEntity("Player");
// 添加组件
player.addComponent(new PositionComponent(400, 300));
player.addComponent(new VelocityComponent(0, 0));
player.addComponent(new HealthComponent(100));
// 使用对象池获取组件
const position = ComponentPoolManager.getInstance().getComponent(PositionComponent);
position.x = 400;
position.y = 300;
player.addComponent(position);
const velocity = ComponentPoolManager.getInstance().getComponent(VelocityComponent);
player.addComponent(velocity);
const health = ComponentPoolManager.getInstance().getComponent(HealthComponent);
health.maxHealth = 100;
health.currentHealth = 100;
player.addComponent(health);
// 设置标签和更新顺序
player.tag = 1; // 玩家标签
@@ -192,45 +237,64 @@ class GameManager {
return player;
}
public createEnemy(x: number, y: number): Entity {
const enemy = this.scene.createEntity("Enemy");
public createEnemies(count: number): Entity[] {
// 使用批量创建API - 高性能
const enemies = this.scene.createEntities(count, "Enemy");
enemy.addComponent(new PositionComponent(x, y));
enemy.addComponent(new VelocityComponent(50, 0));
enemy.addComponent(new HealthComponent(50));
// 批量配置敌人
enemies.forEach((enemy, index) => {
// 使用对象池获取组件
const position = ComponentPoolManager.getInstance().getComponent(PositionComponent);
position.x = Math.random() * 800;
position.y = Math.random() * 600;
enemy.addComponent(position);
const velocity = ComponentPoolManager.getInstance().getComponent(VelocityComponent);
velocity.x = (Math.random() - 0.5) * 100;
velocity.y = (Math.random() - 0.5) * 100;
enemy.addComponent(velocity);
const health = ComponentPoolManager.getInstance().getComponent(HealthComponent);
health.maxHealth = 50;
health.currentHealth = 50;
enemy.addComponent(health);
enemy.tag = 2; // 敌人标签
enemy.updateOrder = 1;
});
enemy.tag = 2; // 敌人标签
enemy.updateOrder = 1;
return enemies;
}
public destroyEntity(entity: Entity): void {
// 释放组件回对象池
entity.components.forEach(component => {
ComponentPoolManager.getInstance().releaseComponent(component);
});
return enemy;
// 销毁实体
entity.destroy();
}
}
```
## 使
### 3. 创建系统
```typescript
class GameManager {
// ... 之前的代码 ...
private updateSystems(deltaTime: number): void {
this.updateMovementSystem(deltaTime);
this.updateHealthSystem(deltaTime);
this.updateCollisionSystem();
}
private updateMovementSystem(deltaTime: number): void {
// 查询所有具有位置和速度组件的实体
const movableEntities = this.querySystem.queryTwoComponents(
import { EntitySystem, Entity } from '@esengine/ecs-framework';
class MovementSystem extends EntitySystem {
protected process(entities: Entity[]): void {
// 使用高性能查询获取移动实体
const movableEntities = this.scene.querySystem.queryTwoComponents(
PositionComponent,
VelocityComponent
);
movableEntities.forEach(({ entity, component1: position, component2: velocity }) => {
// 更新位置
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
position.x += velocity.x * Time.deltaTime;
position.y += velocity.y * Time.deltaTime;
// 边界检查
if (position.x < 0 || position.x > 800) {
@@ -241,177 +305,95 @@ class GameManager {
}
});
}
private updateHealthSystem(deltaTime: number): void {
// 查询所有具有生命值组件的实体
const healthEntities = this.querySystem.queryComponentTyped(HealthComponent);
}
class HealthSystem extends EntitySystem {
protected process(entities: Entity[]): void {
const healthEntities = this.scene.querySystem.queryComponentTyped(HealthComponent);
const deadEntities: Entity[] = [];
healthEntities.forEach(({ entity, component: health }) => {
// 检查死亡
if (health.isDead()) {
deadEntities.push(entity);
}
});
// 移除死亡实体
// 销毁死亡实体
deadEntities.forEach(entity => {
entity.destroy();
});
}
private updateCollisionSystem(): void {
// 获取玩家
const players = this.scene.findEntitiesByTag(1); // 玩家标签
const enemies = this.scene.findEntitiesByTag(2); // 敌人标签
players.forEach(player => {
const playerPos = player.getComponent(PositionComponent);
const playerHealth = player.getComponent(HealthComponent);
if (!playerPos || !playerHealth) return;
enemies.forEach(enemy => {
const enemyPos = enemy.getComponent(PositionComponent);
if (!enemyPos) return;
// 简单的距离检测
const distance = Math.sqrt(
Math.pow(playerPos.x - enemyPos.x, 2) +
Math.pow(playerPos.y - enemyPos.y, 2)
);
if (distance < 50) { // 碰撞距离
playerHealth.takeDamage(10);
console.log(`当前生命值: ${playerHealth.currentHealth}`);
}
});
this.scene.removeEntity(entity);
});
}
}
```
## 使用事件系统
## 高级功能
框架内置了事件系统,用于组件间通信:
### 1. 性能监控
```typescript
// 定义事件类型
enum GameEvents {
PLAYER_DIED = 'playerDied',
ENEMY_SPAWNED = 'enemySpawned',
SCORE_CHANGED = 'scoreChanged'
}
class GameManager {
// ... 之前的代码 ...
constructor() {
// ... 之前的代码 ...
public getPerformanceStats(): void {
const stats = this.scene.getPerformanceStats();
console.log(`实体数量: ${stats.entityCount}`);
console.log(`查询缓存大小: ${stats.queryCacheSize}`);
// 监听事件
this.emitter.on(GameEvents.PLAYER_DIED, this.onPlayerDied.bind(this));
this.emitter.on(GameEvents.ENEMY_SPAWNED, this.onEnemySpawned.bind(this));
}
private onPlayerDied(player: Entity): void {
console.log('游戏结束!');
// 重置游戏或显示游戏结束界面
}
private onEnemySpawned(enemy: Entity): void {
console.log('新敌人出现!');
}
private updateHealthSystem(deltaTime: number): void {
const healthEntities = this.querySystem.queryComponentTyped(HealthComponent);
healthEntities.forEach(({ entity, component: health }) => {
if (health.isDead()) {
// 发送死亡事件
if (entity.tag === 1) { // 玩家
this.emitter.emit(GameEvents.PLAYER_DIED, entity);
}
entity.destroy();
}
});
const poolStats = ComponentPoolManager.getInstance().getPoolStats();
console.log('组件池统计:', poolStats);
}
}
```
## 使用定时器
框架提供了强大的定时器系统:
### 2. 批量操作
```typescript
class GameManager {
// ... 之前的代码 ...
public startGame(): void {
// 创建玩家
this.createPlayer();
// 每2秒生成一个敌人
Core.schedule(2.0, true, this, (timer) => {
const x = Math.random() * 800;
const y = Math.random() * 600;
const enemy = this.createEnemy(x, y);
this.emitter.emit(GameEvents.ENEMY_SPAWNED, enemy);
});
// 5秒后增加敌人生成速度
Core.schedule(5.0, false, this, (timer) => {
console.log('游戏难度提升!');
// 可以在这里修改敌人生成间隔
});
}
}
// 批量创建大量实体
const bullets = this.scene.createEntities(1000, "Bullet");
// 批量查询
const enemies = this.scene.getEntitiesWithComponents([PositionComponent, HealthComponent]);
// 延迟缓存清理(高性能)
bullets.forEach(bullet => {
this.scene.addEntity(bullet, false); // 延迟清理
});
this.scene.querySystem.clearCache(); // 手动清理
```
### 3. 事件系统
```typescript
import { Core, CoreEvents } from '@esengine/ecs-framework';
// 监听事件
Core.emitter.addObserver(CoreEvents.frameUpdated, this.onFrameUpdate, this);
// 发射自定义事件
Core.emitter.emit("playerDied", { player: entity, score: 1000 });
// 移除监听
Core.emitter.removeObserver(CoreEvents.frameUpdated, this.onFrameUpdate);
```
## 完整示例
以下是一个完整的小游戏示例,展示了框架的主要功能:
```typescript
// 导入框架
import { Core } from './Core';
import { Entity } from './ECS/Entity';
import { Component } from './ECS/Component';
import { Scene } from './ECS/Scene';
import { QuerySystem } from './ECS/Core/QuerySystem';
import { Emitter } from './Utils/Emitter';
import {
Core,
Entity,
Component,
Scene,
EntitySystem,
ComponentPoolManager,
BitMaskOptimizer,
Time
} from '@esengine/ecs-framework';
// 定义组件
class PositionComponent extends Component {
constructor(public x: number = 0, public y: number = 0) {
super();
}
}
class VelocityComponent extends Component {
constructor(public x: number = 0, public y: number = 0) {
super();
}
}
class HealthComponent extends Component {
constructor(public maxHealth: number = 100) {
super();
this.currentHealth = maxHealth;
}
public currentHealth: number;
public takeDamage(damage: number): void {
this.currentHealth = Math.max(0, this.currentHealth - damage);
}
public isDead(): boolean {
return this.currentHealth <= 0;
}
}
// 定义组件(前面已定义)
// ... PositionComponent, VelocityComponent, HealthComponent ...
// 游戏事件
enum GameEvents {
@@ -423,141 +405,124 @@ enum GameEvents {
class SimpleGame {
private core: Core;
private scene: Scene;
private querySystem: QuerySystem;
private emitter: Emitter;
private isRunning: boolean = false;
constructor() {
this.core = Core.create(true);
this.scene = new Scene();
this.scene.name = "SimpleGame";
this.querySystem = this.scene.querySystem;
this.emitter = Core.emitter;
// 设置场景
this.scene.name = "GameScene";
Core.scene = this.scene;
// 监听事件
this.emitter.on(GameEvents.PLAYER_DIED, () => {
console.log('游戏结束!');
this.isRunning = false;
this.setupOptimizations();
this.setupSystems();
this.setupEvents();
}
private setupOptimizations(): void {
// 预热组件池
ComponentPoolManager.getInstance().preWarmPools({
PositionComponent: 2000,
VelocityComponent: 2000,
HealthComponent: 1000
});
// 注册位掩码优化
const optimizer = BitMaskOptimizer.getInstance();
optimizer.registerComponentType(PositionComponent);
optimizer.registerComponentType(VelocityComponent);
optimizer.registerComponentType(HealthComponent);
optimizer.precomputeCommonMasks();
}
private setupSystems(): void {
this.scene.addEntityProcessor(new MovementSystem());
this.scene.addEntityProcessor(new HealthSystem());
}
private setupEvents(): void {
Core.emitter.addObserver(GameEvents.PLAYER_DIED, this.onPlayerDied, this);
Core.emitter.addObserver(GameEvents.ENEMY_SPAWNED, this.onEnemySpawned, this);
}
public start(): void {
console.log('游戏开始!');
this.isRunning = true;
// 创建玩家
// 创建游戏实体
this.createPlayer();
// 定期生成敌人
Core.schedule(2.0, true, this, (timer) => {
if (this.isRunning) {
this.createEnemy();
}
});
this.createEnemies(100);
// 启动游戏循环
this.gameLoop();
}
public stop(): void {
this.isRunning = false;
// 清理组件池
ComponentPoolManager.getInstance().clearAllPools();
}
private createPlayer(): Entity {
const player = this.scene.createEntity("Player");
player.addComponent(new PositionComponent(400, 300));
player.addComponent(new VelocityComponent(100, 0));
player.addComponent(new HealthComponent(100));
player.tag = 1; // 玩家标签
const position = ComponentPoolManager.getInstance().getComponent(PositionComponent);
position.x = 400;
position.y = 300;
player.addComponent(position);
const velocity = ComponentPoolManager.getInstance().getComponent(VelocityComponent);
player.addComponent(velocity);
const health = ComponentPoolManager.getInstance().getComponent(HealthComponent);
health.maxHealth = 100;
health.currentHealth = 100;
player.addComponent(health);
player.tag = 1;
return player;
}
private createEnemy(): Entity {
const enemy = this.scene.createEntity("Enemy");
const x = Math.random() * 800;
const y = Math.random() * 600;
private createEnemies(count: number): Entity[] {
// 使用高性能批量创建
const enemies = this.scene.createEntities(count, "Enemy");
enemy.addComponent(new PositionComponent(x, y));
enemy.addComponent(new VelocityComponent(-50, 0));
enemy.addComponent(new HealthComponent(50));
enemy.tag = 2; // 敌人标签
enemies.forEach((enemy, index) => {
const position = ComponentPoolManager.getInstance().getComponent(PositionComponent);
position.x = Math.random() * 800;
position.y = Math.random() * 600;
enemy.addComponent(position);
const velocity = ComponentPoolManager.getInstance().getComponent(VelocityComponent);
velocity.x = (Math.random() - 0.5) * 100;
velocity.y = (Math.random() - 0.5) * 100;
enemy.addComponent(velocity);
const health = ComponentPoolManager.getInstance().getComponent(HealthComponent);
health.maxHealth = 50;
health.currentHealth = 50;
enemy.addComponent(health);
enemy.tag = 2;
});
this.emitter.emit(GameEvents.ENEMY_SPAWNED, enemy);
return enemy;
return enemies;
}
private onPlayerDied(event: any): void {
console.log("游戏结束!玩家死亡");
this.stop();
}
private onEnemySpawned(event: any): void {
console.log("敌人出现!");
}
private update(deltaTime: number): void {
// 更新定时器
this.core._timerManager.update(deltaTime);
// 更新场景
this.scene.update();
// 更新游戏系统
this.updateMovement(deltaTime);
this.updateCollision();
this.updateHealth();
}
private updateMovement(deltaTime: number): void {
const movableEntities = this.querySystem.queryTwoComponents(
PositionComponent,
VelocityComponent
);
movableEntities.forEach(({ entity, component1: pos, component2: vel }) => {
pos.x += vel.x * deltaTime;
pos.y += vel.y * deltaTime;
// 边界检查
if (pos.x < 0 || pos.x > 800) vel.x = -vel.x;
if (pos.y < 0 || pos.y > 600) vel.y = -vel.y;
});
}
private updateCollision(): void {
const players = this.scene.findEntitiesByTag(1);
const enemies = this.scene.findEntitiesByTag(2);
players.forEach(player => {
const playerPos = player.getComponent(PositionComponent);
const playerHealth = player.getComponent(HealthComponent);
if (!playerPos || !playerHealth) return;
enemies.forEach(enemy => {
const enemyPos = enemy.getComponent(PositionComponent);
if (!enemyPos) return;
const distance = Math.sqrt(
Math.pow(playerPos.x - enemyPos.x, 2) +
Math.pow(playerPos.y - enemyPos.y, 2)
);
if (distance < 50) {
playerHealth.takeDamage(10);
console.log(`玩家生命值: ${playerHealth.currentHealth}`);
}
});
});
}
private updateHealth(): void {
const healthEntities = this.querySystem.queryComponentTyped(HealthComponent);
const deadEntities: Entity[] = [];
healthEntities.forEach(({ entity, component: health }) => {
if (health.isDead()) {
deadEntities.push(entity);
if (entity.tag === 1) { // 玩家死亡
this.emitter.emit(GameEvents.PLAYER_DIED, entity);
}
}
});
// 移除死亡实体
deadEntities.forEach(entity => {
entity.destroy();
});
}
private gameLoop(): void {
@@ -584,6 +549,23 @@ const game = new SimpleGame();
game.start();
```
## 性能优化建议
### 1. 大规模实体处理
- 使用 `createEntities()` 批量创建实体
- 启用组件对象池减少内存分配
- 使用延迟缓存清理机制
### 2. 查询优化
- 缓存频繁查询的结果
- 使用 `BitMaskOptimizer` 优化掩码操作
- 减少不必要的查询频率
### 3. 内存管理
- 预热常用组件池
- 及时释放不用的组件回对象池
- 定期清理未使用的缓存
## 下一步
现在您已经掌握了 ECS Framework 的基础用法,可以继续学习:
@@ -591,13 +573,14 @@ game.start();
- [实体使用指南](entity-guide.md) - 详细了解实体的所有功能和用法
- [核心概念](core-concepts.md) - 深入了解 ECS 架构和设计原理
- [查询系统使用指南](query-system-usage.md) - 学习高性能查询系统的详细用法
- [性能基准](performance.md) - 了解框架的性能表现和优化建议
## 常见问题
### Q: 如何在不同游戏引擎中集成?
A: ECS Framework 是引擎无关的,您只需要:
1. 将框架源码复制到项目中
1. 通过npm安装框架 `npm install @esengine/ecs-framework`
2. 在游戏引擎的主循环中调用 `scene.update()`
3. 根据需要集成渲染、输入等引擎特定功能
@@ -605,22 +588,20 @@ A: ECS Framework 是引擎无关的,您只需要:
A: 框架本身不提供输入处理,建议:
1. 创建一个输入组件来存储输入状态
2. 在游戏循环中更新输入状态
3. 在相关组件中读取输入状态并处理
2. 在游戏引擎的输入回调中更新输入组件
3. 创建输入处理系统来响应输入状态
### Q: 如何调试
### Q: 如何优化大规模实体性能
A: 框架提供了多种调试功能
- 使用 `entity.getDebugInfo()` 查看实体信息
- 使用 `querySystem.getPerformanceReport()` 查看查询性能
- 使用 `querySystem.getStats()` 查看详细统计信息
A: 关键优化策略
1. 启用组件对象池:`ComponentPoolManager.getInstance().registerPool()`
2. 使用批量操作:`scene.createEntities()`
3. 缓存查询结果,减少查询频率
4. 使用位掩码优化器:`BitMaskOptimizer.getInstance()`
### Q: 性能如何优化
### Q: 组件对象池何时有效
A: 框架已经内置了多种性能优化
- 使用位掩码进行快速组件匹配
- 多级索引系统加速查询
- 智能缓存减少重复计算
- 批量操作减少开销
建议定期调用 `querySystem.optimizeIndexes()` 来自动优化配置。
A: 对象池在以下情况下最有效
- 频繁创建和销毁相同类型的组件
- 组件数量大于1000个
- 游戏运行时间较长,需要避免垃圾回收压力

View File

@@ -5,204 +5,302 @@
## 🚀 快速测试
```bash
# 在项目根目录运行
node benchmark.js
# 快速性能基准测试
npm run benchmark
# 完整性能测试
npm run test:performance
# 单元测试
npm run test:unit
```
## 📊 性能基准数据
> 测试环境: Node.js, 现代桌面CPU
> 测试时间: 2025年
> 测试环境: Node.js, Windows 10, 现代桌面CPU
### 1. 实体创建性能
| 实体数量 | 创建时间 | 创建速度 | 每个实体耗时 |
|---------|---------|---------|-------------|
| 1,000 | 1.11ms | 903,751个/秒 | 0.0011ms |
| 5,000 | 3.47ms | 1,441,462个/秒 | 0.0007ms |
| 10,000 | 6.91ms | 1,446,341个/秒 | 0.0007ms |
| 20,000 | 7.44ms | 2,686,764个/秒 | 0.0004ms |
| 50,000 | 22.73ms | 2,199,659个/秒 | 0.0005ms |
| 实体数量 | 创建时间 | 创建速度 | 每个实体耗时 | 性能等级 |
|---------|---------|---------|-------------|---------|
| 1,000 | 1.56ms | 640,697个/秒 | 0.0016ms | 🚀 极致 |
| 5,000 | 19.47ms | 256,805个/秒 | 0.0039ms | 🚀 极致 |
| 10,000 | 39.94ms | 250,345个/秒 | 0.0040ms | 🚀 极致 |
| 50,000 | 258.17ms | 193,673个/秒 | 0.0052ms | ✅ 优秀 |
| 100,000 | 463.04ms | 215,963个/秒 | 0.0046ms | ✅ 优秀 |
| 500,000 | 3,087ms | 161,990个/秒 | 0.0062ms | ✅ 优秀 |
**结论**: 实体创建性能优秀,平均每秒可创建 **220万+个实体**
**结论**: 🚀 实体创建性能达到极致水平大规模创建50万实体仅需3秒
### 2. 组件访问性能
### 2. 性能瓶颈分析 (500,000个实体)
| 迭代次数 | 总耗时 | 访问速度 | 每次访问耗时 |
|---------|--------|---------|-------------|
| 100次 | 13.27ms | 37,678,407次/秒 | 0.027μs |
| 500次 | 34.27ms | 72,957,553次/秒 | 0.014μs |
| 1000次 | 68.85ms | 72,624,911次/秒 | 0.014μs |
| 2000次 | 139.67ms | 71,598,669次/秒 | 0.014μs |
**当前瓶颈分布**:
```
实体创建: 46.3% (1,429ms)
组件添加: 53.5% (1,651ms) ← 主要瓶颈
标签分配: 0.2% (7ms)
```
**结论**: ✅ 组件访问性能优秀,平均每秒可访问 **7200万+次**
**特征**: 框架实现了均衡的性能分布,各部分开销相对合理
### 3. 组件操作性能
### 3. 组件添加性能详细分析
| 迭代次数 | 总耗时 | 操作速度 | 每次操作耗时 |
|---------|--------|---------|-------------|
| 100次 | 36.89ms | 27,105,193次/秒 | 0.037μs |
| 500次 | 147.42ms | 33,915,665次/秒 | 0.029μs |
| 1000次 | 289.66ms | 34,522,936次/秒 | 0.029μs |
| 组件类型 | 添加速度 | 平均耗时 | 性能等级 |
|---------|---------|---------|---------|
| PositionComponent | 596,929组件/秒 | 0.0017ms | 🚀 极致 |
| VelocityComponent | 1,186,770组件/秒 | 0.0008ms | 🚀 极致 |
| HealthComponent | 841,982组件/秒 | 0.0012ms | 🚀 极致 |
| RenderComponent | 763,351组件/秒 | 0.0013ms | 🚀 极致 |
| AIComponent | 185,964组件/秒 | 0.0054ms | ✅ 优秀 |
**结论**: ✅ 组件添加/删除性能优秀,平均每秒可操作 **3450万+次**
### 4. 优化技术性能影响
### 4. 查询系统性能
| 优化技术 | 性能提升 | 内存影响 | 适用场景 |
|---------|---------|---------|---------|
| 组件对象池 | 30-50% | 减少分配 | 频繁创建/销毁 |
| 位掩码优化器 | 20-40% | 缓存开销 | 大量查询操作 |
| 批量操作 | 显著提升 | 无明显影响 | 大规模实体创建 |
| 延迟索引更新 | 60-80% | 临时内存增加 | 批量实体操作 |
| 索引去重优化 | 避免O(n) | 轻微内存增加 | 防止重复实体 |
#### 4.1 单组件查询
| 查询次数 | 总耗时 | 查询速度 | 每次查询耗时 |
|---------|--------|---------|-------------|
| 100次 | 10.37ms | 9,639次/秒 | 0.104ms |
| 500次 | 41.17ms | 12,144次/秒 | 0.082ms |
| 1000次 | 82.11ms | 12,178次/秒 | 0.082ms |
### 5. 查询系统性能
#### 4.2 多组件查询
| 查询次数 | 总耗时 | 查询速度 | 每次查询耗时 |
|---------|--------|---------|-------------|
| 100次 | 11.22ms | 8,914次/秒 | 0.112ms |
| 500次 | 54.85ms | 9,116次/秒 | 0.110ms |
| 1000次 | 105.94ms | 9,439次/秒 | 0.106ms |
#### 5.1 基础查询性能
| 查询类型 | 查询速度 | 每次查询耗时 | 性能等级 |
|---------|---------|-------------|---------|
| 单组件查询 | 12,178次/秒 | 0.082ms | ✅ 优秀 |
| 多组件查询 | 9,439次/秒 | 0.106ms | ✅ 优秀 |
| 复合查询 | 7,407次/秒 | 0.135ms | ✅ 良好 |
#### 4.3 复合查询 (组件+标签)
| 查询次数 | 总耗时 | 查询速度 | 每次查询耗时 |
|---------|--------|---------|-------------|
| 100次 | 15.80ms | 6,327次/秒 | 0.158ms |
| 500次 | 65.77ms | 7,602次/秒 | 0.132ms |
| 1000次 | 135.01ms | 7,407次/秒 | 0.135ms |
#### 5.2 缓存查询性能
| 缓存状态 | 访问速度 | 性能特征 |
|---------|---------|---------|
| 缓存命中 | 零延迟 | 🚀 即时响应 |
| 缓存未命中 | 标准查询 | ✅ 自动构建 |
| 缓存清理 | 批量延迟 | 🔧 优化策略 |
**结论**: ⚠️ 查询性能正常,平均每秒可查询 **12000+次**
### 6. 新功能性能基准
### 5. 性能极限测试
#### 6.1 组件对象池性能
```
📊 对象池 vs 直接创建 (10,000次操作)
对象池获取: 1.65ms (6,060,606次/秒)
直接创建: 1.51ms (6,622,516次/秒)
⚠️ 小规模测试中对象池可能略慢,但在大规模应用中:
- 减少30-50%的内存分配
- 避免垃圾回收压力
- 提升长期运行稳定性
```
| 实体数量 | 创建时间 | 处理时间/帧 | FPS | 状态 |
|---------|---------|------------|-----|------|
| 10,000 | 1.55ms | 0.137ms | 7264.0 | ✅ |
| 25,000 | 3.91ms | 0.432ms | 2311.4 | ✅ |
| 50,000 | 12.40ms | 1.219ms | 820.0 | ✅ |
| 100,000 | 58.93ms | 2.976ms | 335.9 | ✅ |
| 200,000 | 51.43ms | 6.031ms | 165.8 | ✅ |
#### 6.2 位掩码优化器性能
```
🔥 位掩码操作性能 (100,000次操作)
单个掩码创建: 20.00ms (5,000,000次/秒)
组合掩码创建: 53.69ms (1,862,285次/秒)
缓存掩码访问: <1ms (近零延迟)
```
**结论**: 🚀 框架极限性能优秀,可处理 **20万个实体@165.8FPS** 仍维持高性能
## 🎯 性能扩展性分析
## 🎯 性能瓶颈分析
### 实体创建扩展性
```
📈 创建速度趋势分析
1K-10K实体: 250,000-640,000 实体/秒 (优秀)
10K-100K实体: 200,000-250,000 实体/秒 (良好)
100K-500K实体: 160,000-220,000 实体/秒 (稳定)
结论: 性能随规模稳定下降,无突然性能悬崖
```
### 主要瓶颈
1. **查询系统** (相对瓶颈)
- 单组件查询: ~12,000次/秒
- 多组件查询: ~9,400次/秒
- 复合查询: ~7,400次/秒
- **原因**: 需要遍历所有实体进行过滤
2. **大规模实体处理** (可接受)
- 10万个实体: 335.9 FPS
- 20万个实体: 165.8 FPS
- **原因**: 线性时间复杂度,符合预期
### 非瓶颈项
**实体创建**: 220万+个/秒,性能优秀
**组件访问**: 7200万+次/秒,性能优秀
**组件操作**: 3450万+次/秒,性能优秀
**系统处理**: 20万个实体@165.8FPS,性能优秀
## 📈 时间复杂度分析
| 操作类型 | 时间复杂度 | 性能等级 | 说明 |
|---------|-----------|---------|------|
| 实体创建 | O(1) | ✅ 优秀 | 常数时间创建 |
| 组件访问 | O(1) | ✅ 优秀 | 哈希表查找 |
| 组件操作 | O(1) | ✅ 优秀 | 常数时间添加/删除 |
| 单组件查询 | O(n) | ⚠️ 正常 | 线性遍历实体 |
| 多组件查询 | O(n×m) | ⚠️ 正常 | 遍历实体×组件数 |
| 系统处理 | O(n) | ✅ 优秀 | 线性处理实体 |
### 内存使用效率
| 实体数量 | 内存使用 | 每实体内存 | 内存效率 |
|---------|---------|-----------|---------|
| 1,000 | 3.5MB | 3.5KB | 🚀 极致 |
| 5,000 | 7.1MB | 1.4KB | 🚀 极致 |
| 10,000 | 20.8MB | 2.1KB | ✅ 优秀 |
| 50,000 | ~100MB | ~2KB | ✅ 优秀 |
## 💡 性能优化建议
### 对于查询密集型应用
### 1. 实体创建最佳实践
1. **缓存查询结果**
```typescript
// 缓存常用查询
const cachedPlayers = scene.getEntitiesWithComponents([Position, Player]);
```
**✅ 推荐做法**:
```typescript
// 使用批量创建API
const entities = scene.createEntities(10000, "Enemies");
2. **减少查询频率**
```typescript
// 每5帧查询一次而不是每帧
if (frameCount % 5 === 0) {
updateEnemyList();
}
```
// 延迟缓存清理
entities.forEach(entity => {
scene.addEntity(entity, false); // 延迟清理
});
scene.querySystem.clearCache(); // 手动清理
```
3. **使用更精确的查询**
```typescript
// 优先使用单组件查询
const entities = scene.getEntitiesWithComponent(Position);
```
**❌ 避免做法**:
```typescript
// 避免循环单个创建
for (let i = 0; i < 10000; i++) {
scene.createEntity("Enemy" + i); // 每次触发缓存清理
}
```
### 对于大规模实体应用
### 2. 组件池优化策略
1. **分批处理**
```typescript
// 分批处理大量实体
const batchSize = 1000;
for (let i = 0; i < entities.length; i += batchSize) {
processBatch(entities.slice(i, i + batchSize));
}
```
**预热策略**:
```typescript
// 预热常用组件池
ComponentPoolManager.getInstance().preWarmPools({
BulletComponent: 2000, // 子弹大量创建
EffectComponent: 1000, // 特效频繁使用
PickupComponent: 500 // 道具适量缓存
});
```
2. **LOD系统**
```typescript
// 根据距离调整处理频率
if (distance > 100) {
if (frameCount % 10 !== 0) continue; // 远距离实体降低更新频率
}
```
**使用模式**:
```typescript
// 高效的组件复用
const bullet = ComponentPoolManager.getInstance().getComponent(BulletComponent);
bullet.reset(); // 重置状态
entity.addComponent(bullet);
## 🌍 实际应用指南
// 销毁时释放到池
ComponentPoolManager.getInstance().releaseComponent(bullet);
```
### 不同平台的建议
### 3. 查询优化策略
| 平台 | 推荐实体数量 | 查询频率 | 备注 |
|------|-------------|---------|------|
| 桌面端 | ≤100,000 | 高频查询可接受 | 性能充足 |
| Web端 | ≤50,000 | 中等查询频率 | 考虑浏览器限制 |
| 移动端 | ≤20,000 | 低频查询 | 性能和电池优化 |
**缓存策略**:
```typescript
// 缓存频繁查询结果
class MovementSystem extends EntitySystem {
private cachedMovingEntities: Entity[];
private lastCacheFrame: number = 0;
protected process(entities: Entity[]) {
// 每5帧更新一次缓存
if (Time.frameCount - this.lastCacheFrame > 5) {
this.cachedMovingEntities = scene.getEntitiesWithComponents([Position, Velocity]);
this.lastCacheFrame = Time.frameCount;
}
// 使用缓存结果
this.processMovement(this.cachedMovingEntities);
}
}
```
### 游戏类型建议
### 4. 不同规模应用建议
| 游戏类型 | 典型实体数 | 主要瓶颈 | 优化重点 |
|---------|-----------|---------|---------|
| 2D平台游戏 | 1,000-5,000 | 无明显瓶颈 | 专注游戏逻辑 |
| 2D射击游戏 | 5,000-20,000 | 碰撞检测 | 空间分割算法 |
| RTS游戏 | 10,000-50,000 | 查询系统 | 缓存+分批处理 |
| MMO游戏 | 50,000+ | 网络+查询 | 分区+优化查询 |
#### 小型游戏 (< 5,000实体)
- ✅ 可以随意使用所有功能
- ✅ 不需要特殊优化
- ✅ 专注于游戏逻辑开发
## 🔬 测试方法
#### 中型游戏 (5,000-50,000实体)
- ✅ 使用批量操作API
- ✅ 启用组件对象池
- ⚠️ 注意查询频率
### 运行完整基准测试
#### 大型游戏 (50,000+实体)
- 🚀 必须使用批量操作
- 🚀 必须启用对象池
- 🚀 必须缓存查询结果
- 🚀 考虑分区处理
## 🌍 平台性能对比
### Windows 桌面端 (测试平台)
- **实体创建**: 640,697实体/秒
- **组件操作**: 596,929组件/秒
- **推荐实体数**: ≤ 200,000
### 预估其他平台性能
| 平台类型 | 预估性能比例 | 推荐实体数 | 特殊注意 |
|---------|-------------|-----------|---------|
| macOS桌面 | 90-100% | ≤ 180,000 | 内存管理优秀 |
| Linux桌面 | 95-105% | ≤ 200,000 | 性能最优 |
| Chrome浏览器 | 60-80% | ≤ 100,000 | V8引擎优化 |
| Firefox浏览器 | 50-70% | ≤ 80,000 | SpiderMonkey限制 |
| Safari浏览器 | 55-75% | ≤ 90,000 | JavaScriptCore |
| Node.js服务器 | 100-110% | ≤ 500,000 | 服务器级性能 |
| Android Chrome | 30-50% | ≤ 30,000 | 移动端限制 |
| iOS Safari | 40-60% | ≤ 40,000 | iOS优化较好 |
## 🔬 测试环境详情
### 硬件环境
- **操作系统**: Windows 10 (Build 26100)
- **处理器**: 现代桌面CPU
- **内存**: 充足RAM
- **存储**: SSD高速存储
### 软件环境
- **Node.js**: v16+
- **TypeScript**: v5.8.3
- **ECS框架版本**: v2.0.6
- **测试工具**: 内置基准测试套件
### 测试方法
- **实体配置**: 位置、速度、生命值、渲染、AI组件随机分配
- **测试迭代**: 多次测试取平均值
- **内存监控**: 实时内存使用情况
- **性能指标**: performance.now()高精度计时
## 📋 性能测试清单
### 运行完整性能测试
```bash
# 项目根目录
node benchmark.js
# 1. 快速基准测试 (2-3分钟)
npm run benchmark
# 2. 完整性能测试 (10-15分钟)
npm run test:performance
# 3. 单元测试验证 (30秒)
npm run test:unit
# 4. 所有测试 (15-20分钟)
npm run test
```
### 自定义测试
### 自定义性能测试
```typescript
// 在source目录下
npm run test:framework:benchmark
import { runEntityCreationBenchmark } from '@esengine/ecs-framework/Testing/Performance/benchmark';
// 自定义规模测试
await runEntityCreationBenchmark([1000, 5000, 10000]);
// 组件性能测试
await runComponentPerformanceTest();
// 查询性能测试
await runQueryPerformanceTest();
```
## 📝 测试环境
## 🏆 性能总结
- **Node.js版本**: 16+
- **TypeScript版本**: 5.8.3
- **测试实体数**: 5,000个 (带position、velocity组件)
- **测试迭代**: 多次取平均值
- **硬件**: 现代桌面CPU
### 🎯 核心能力
1. **实体创建速度**: 最高64万实体/秒
2. **大规模处理**: 50万实体仅需3秒创建
3. **均衡性能**: 各组件开销分布合理
4. **扩展性**: 性能随规模线性下降,无突然悬崖
### 🔧 技术特点
1. **批量操作架构** - 大幅减少单次操作开销
2. **智能缓存策略** - 延迟清理机制
3. **索引系统优化** - 避免O(n)操作
4. **内存管理优化** - 对象池和位掩码缓存
### 🌟 实际应用价值
- **小型游戏**: 性能过剩,专注玩法
- **中型游戏**: 性能充足,适度优化
- **大型游戏**: 需要优化策略,但完全可行
- **服务器端**: 可处理大规模实体管理
---
**结论**: ECS框架本身性能优秀,能够满足大多数应用需求。性能瓶颈主要来自于**业务逻辑的算法选择**而非框架架构
**结论**: ECS框架达到了产品级性能标准能够满足从休闲小游戏到复杂RTS游戏的各种需求。框架层面的性能已经充分优化为开发者提供了坚实的性能基础

View File

@@ -7,15 +7,14 @@ QuerySystem 是 ECS Framework 中的高性能实体查询系统,支持多级
### 1. 获取查询系统
```typescript
import { Scene } from './ECS/Scene';
import { Entity } from './ECS/Entity';
import { Scene, Entity } from '@esengine/ecs-framework';
// 创建场景,查询系统会自动创建
const scene = new Scene();
const querySystem = scene.querySystem;
// 或者从Core获取当前场景的查询系统
import { Core } from './Core';
import { Core } from '@esengine/ecs-framework';
const currentQuerySystem = Core.scene?.querySystem;
```
@@ -206,7 +205,7 @@ console.log(`新增: ${diff.added.length}, 移除: ${diff.removed.length}`);
### 移动系统示例
```typescript
import { EntitySystem } from './ECS/Systems/EntitySystem';
import { EntitySystem } from '@esengine/ecs-framework';
class MovementSystem extends EntitySystem {
public update(): void {