Files
esengine/docs/entity-manager-example.md

11 KiB
Raw Blame History

EntityManager 使用指南

EntityManager 是 ECS Framework 的核心管理系统,提供统一的实体管理、高性能查询和自动优化功能。

快速开始

创建实体管理器

import { EntityManager, Scene } from '@esengine/ecs-framework';

// 通常在游戏管理器中创建
const scene = new Scene();
const entityManager = new EntityManager(scene);

基础实体操作

// 创建单个实体
const player = entityManager.createEntity("Player");
player.addComponent(new PositionComponent(100, 100));
player.addComponent(new HealthComponent(100));
player.tag = "player";

// 批量创建实体
const enemies = entityManager.createEntities(50, "Enemy");
enemies.forEach((enemy, index) => {
    enemy.addComponent(new PositionComponent(
        Math.random() * 800, 
        Math.random() * 600
    ));
    enemy.addComponent(new HealthComponent(30));
    enemy.tag = "enemy";
});

// 销毁实体
entityManager.destroyEntity(player);

高性能查询系统

EntityManager 提供多种查询方式,自动选择最优的查询策略。

基础查询

// 通过ID查询O(1)
const entity = entityManager.getEntity(123);

// 通过名称查询O(1) 哈希查找)
const player = entityManager.getEntityByName("Player");

// 通过标签查询O(1) 索引查找)
const enemies = entityManager.getEntitiesByTag("enemy");

// 组件查询使用O(1)组件索引)
const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);

// 多组件查询使用Archetype优化
const movingEntities = entityManager.getEntitiesWithComponents([
    PositionComponent, 
    VelocityComponent
]);

流式查询API

EntityManager 提供强大的流式查询构建器:

// 基础查询构建
const results = entityManager
    .query()
    .withAll([PositionComponent, HealthComponent])  // 必须包含这些组件
    .withoutTag("dead")                             // 不能有死亡标签
    .active(true)                                   // 必须激活
    .execute();

// 复杂条件查询
const livingEnemies = entityManager
    .query()
    .withAll([PositionComponent, HealthComponent])
    .withTag("enemy")
    .withoutTag("dead")
    .where(entity => {
        const health = entity.getComponent(HealthComponent);
        return health && health.currentHealth > 0;
    })
    .execute();

// 查询变体
const firstEnemy = entityManager
    .query()
    .withTag("enemy")
    .first();                                       // 获取第一个匹配

const enemyCount = entityManager
    .query()
    .withTag("enemy")
    .count();                                       // 获取数量

// 直接处理查询结果
entityManager
    .query()
    .withAll([HealthComponent])
    .forEach(entity => {
        const health = entity.getComponent(HealthComponent);
        if (health.currentHealth <= 0) {
            entity.addTag("dead");
        }
    });

高级查询选项

// 组合条件查询
const combatUnits = entityManager
    .query()
    .withAll([PositionComponent, HealthComponent])   // AND条件
    .withAny([WeaponComponent, MagicComponent])      // OR条件
    .without([DeadComponent])                        // NOT条件
    .withTag("combatant")
    .withoutTag("peaceful")
    .active(true)
    .enabled(true)
    .execute();

// 使用自定义过滤器
const nearbyEnemies = entityManager
    .query()
    .withAll([PositionComponent])
    .withTag("enemy")
    .where(entity => {
        const pos = entity.getComponent(PositionComponent);
        const distance = Math.sqrt(
            Math.pow(pos.x - playerPos.x, 2) + 
            Math.pow(pos.y - playerPos.y, 2)
        );
        return distance < 100; // 距离玩家100像素内
    })
    .execute();

批量操作

EntityManager 提供高效的批量操作方法:

// 遍历所有实体
entityManager.forEachEntity(entity => {
    // 处理每个实体
    if (entity.position.x < 0) {
        entity.position.x = 0;
    }
});

// 遍历特定组件的实体
entityManager.forEachEntityWithComponent(HealthComponent, (entity, health) => {
    if (health.currentHealth <= 0) {
        entity.addTag("dead");
        entity.enabled = false;
    }
});

// 批量创建并配置实体
const bullets = entityManager.createEntities(100, "Bullet", (bullet, index) => {
    bullet.addComponent(new PositionComponent(
        100 + index * 10, 
        100
    ));
    bullet.addComponent(new VelocityComponent(0, -200));
    bullet.tag = "projectile";
});

性能优化系统

EntityManager 内置了三个性能优化系统:

1. 组件索引系统

自动为组件查询提供O(1)性能:

// 获取组件索引统计
const componentIndex = entityManager.getComponentIndex();
const stats = componentIndex.getPerformanceStats();

console.log('组件索引统计:', {
    totalQueries: stats.totalQueries,
    indexHits: stats.indexHits,
    hitRate: (stats.indexHits / stats.totalQueries * 100).toFixed(2) + '%'
});

// 手动优化(通常自动进行)
componentIndex.optimize();

2. Archetype系统

按组件组合分组实体,优化批量查询:

// 获取Archetype统计
const archetypeSystem = entityManager.getArchetypeSystem();
const archetypeStats = archetypeSystem.getStatistics();

console.log('Archetype统计:', {
    totalArchetypes: archetypeStats.totalArchetypes,
    totalEntities: archetypeStats.totalEntities,
    queryCacheSize: archetypeStats.queryCacheSize
});

// 查看所有原型
console.log('当前原型:', archetypeSystem.getAllArchetypes());

3. 脏标记系统

追踪实体变更,避免不必要的更新:

// 获取脏标记统计
const dirtyTracking = entityManager.getDirtyTrackingSystem();
const dirtyStats = dirtyTracking.getPerformanceStats();

console.log('脏标记统计:', {
    totalMarks: dirtyStats.totalMarks,
    batchesProcessed: dirtyStats.batchesProcessed,
    listenersNotified: dirtyStats.listenersNotified
});

// 手动处理脏标记
dirtyTracking.processDirtyMarks();

实体管理器统计

获取EntityManager的综合性能数据

const stats = entityManager.getStatistics();

console.log('EntityManager统计:', {
    // 基础统计
    entityCount: stats.entityCount,
    activeEntityCount: stats.activeEntityCount,
    
    // 查询统计
    totalQueries: stats.totalQueries,
    indexHits: stats.indexHits,
    archetypeHits: stats.archetypeHits,
    
    // 性能指标
    averageQueryTime: stats.averageQueryTime,
    hitRate: (stats.indexHits / stats.totalQueries * 100).toFixed(2) + '%'
});

系统优化和清理

// 手动触发优化
entityManager.optimize();

// 内存清理
entityManager.cleanup();

// 压缩数据结构
entityManager.compact();

// 获取内存使用情况
const memoryStats = entityManager.getMemoryUsage();
console.log('内存使用:', {
    entityIndexSize: memoryStats.entityIndex,
    componentIndexSize: memoryStats.componentIndex,
    archetypeSize: memoryStats.archetype
});

实际使用案例

游戏系统集成

class MovementSystem extends EntitySystem {
    private entityManager: EntityManager;
    
    constructor(scene: Scene) {
        super();
        this.entityManager = new EntityManager(scene);
    }
    
    protected process(entities: Entity[]): void {
        // 使用高效查询获取移动实体
        const movingEntities = this.entityManager
            .query()
            .withAll([PositionComponent, VelocityComponent])
            .active(true)
            .execute();
        
        // 批量处理
        movingEntities.forEach(entity => {
            const position = entity.getComponent(PositionComponent);
            const velocity = entity.getComponent(VelocityComponent);
            
            position.x += velocity.dx * Time.deltaTime;
            position.y += velocity.dy * Time.deltaTime;
        });
    }
}

复杂查询示例

// 战斗系统:查找攻击范围内的敌人
class CombatSystem {
    private entityManager: EntityManager;
    
    findTargetsInRange(attacker: Entity, range: number): Entity[] {
        const attackerPos = attacker.getComponent(PositionComponent);
        if (!attackerPos) return [];
        
        return this.entityManager
            .query()
            .withAll([PositionComponent, HealthComponent])
            .withTag("enemy")
            .withoutTag("dead")
            .where(entity => {
                const pos = entity.getComponent(PositionComponent);
                const distance = Math.sqrt(
                    Math.pow(pos.x - attackerPos.x, 2) + 
                    Math.pow(pos.y - attackerPos.y, 2)
                );
                return distance <= range;
            })
            .execute();
    }
    
    // 优化版本:使用空间分区(如果实现了的话)
    findTargetsInRangeOptimized(attacker: Entity, range: number): Entity[] {
        // 首先通过空间查询缩小范围
        const nearbyEntities = this.spatialIndex.queryRange(
            attackerPos.x - range, 
            attackerPos.y - range,
            attackerPos.x + range, 
            attackerPos.y + range
        );
        
        // 然后使用EntityManager进行精确过滤
        return this.entityManager
            .query()
            .withAll([HealthComponent])
            .withTag("enemy")
            .withoutTag("dead")
            .where(entity => nearbyEntities.includes(entity))
            .execute();
    }
}

性能建议

查询优化

  1. 利用索引: 优先使用组件查询和标签查询它们具有O(1)性能
  2. 减少自定义过滤: where()条件虽然灵活,但会降低性能
  3. 缓存查询结果: 对于不经常变化的查询结果,考虑缓存
// ✅ 推荐:使用索引查询
const enemies = entityManager.getEntitiesByTag("enemy");

// ⚠️ 谨慎:自定义过滤
const enemies = entityManager
    .query()
    .where(entity => entity.name.includes("Enemy"))
    .execute();

批量操作优化

// ✅ 推荐:批量创建
const bullets = entityManager.createEntities(100, "Bullet");

// ❌ 避免:循环单独创建
for (let i = 0; i < 100; i++) {
    entityManager.createEntity("Bullet");
}

内存管理

// 定期清理
setInterval(() => {
    entityManager.cleanup();
}, 30000); // 每30秒清理一次

// 监控性能
const stats = entityManager.getStatistics();
if (stats.indexHits / stats.totalQueries < 0.8) {
    console.warn('查询命中率较低,考虑优化查询策略');
}

总结

EntityManager 提供了:

  • 统一接口: 所有实体操作通过一个管理器完成
  • 自动优化: 内置三个性能优化系统
  • 灵活查询: 从简单的ID查找到复杂的条件查询
  • 性能监控: 完整的统计和诊断信息
  • 批量操作: 高效的批量处理能力

通过合理使用EntityManager您可以构建高性能、可维护的ECS游戏系统。