优化matcher内部实现改为querysystem
完善type类型 更新文档
This commit is contained in:
@@ -44,42 +44,50 @@ for (let i = 0; i < typedResult.entities.length; i++) {
|
||||
}
|
||||
|
||||
// 查询单个组件类型
|
||||
const healthEntities = querySystem.queryComponentTyped(HealthComponent);
|
||||
healthEntities.forEach(({ entity, component }) => {
|
||||
console.log(`实体 ${entity.name} 的生命值: ${component.value}`);
|
||||
});
|
||||
const healthResult = querySystem.queryAll(HealthComponent);
|
||||
for (const entity of healthResult.entities) {
|
||||
const health = entity.getComponent(HealthComponent);
|
||||
if (health) {
|
||||
console.log(`实体 ${entity.name} 的生命值: ${health.value}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询两个组件类型
|
||||
const movableEntities = querySystem.queryTwoComponents(PositionComponent, VelocityComponent);
|
||||
movableEntities.forEach(({ entity, component1: position, component2: velocity }) => {
|
||||
// 更新位置
|
||||
position.x += velocity.x;
|
||||
position.y += velocity.y;
|
||||
});
|
||||
const movableResult = querySystem.queryAll(PositionComponent, VelocityComponent);
|
||||
for (const entity of movableResult.entities) {
|
||||
const position = entity.getComponent(PositionComponent);
|
||||
const velocity = entity.getComponent(VelocityComponent);
|
||||
if (position && velocity) {
|
||||
// 更新位置
|
||||
position.x += velocity.x;
|
||||
position.y += velocity.y;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 使用查询构建器
|
||||
|
||||
```typescript
|
||||
// 创建复杂查询
|
||||
const query = querySystem.createQuery()
|
||||
.withAll(PositionComponent, RenderComponent)
|
||||
.without(HiddenComponent)
|
||||
.withTag(1) // 特定标签
|
||||
.orderByName()
|
||||
.limit(10);
|
||||
// QuerySystem不提供查询构建器,请使用Matcher进行复杂查询
|
||||
// 推荐使用Matcher配合EntitySystem
|
||||
|
||||
const result = query.execute();
|
||||
import { Matcher } from '@esengine/ecs-framework';
|
||||
|
||||
// 链式操作
|
||||
const visibleEnemies = querySystem.createQuery()
|
||||
.withAll(EnemyComponent, PositionComponent)
|
||||
.without(DeadComponent, HiddenComponent)
|
||||
// 创建复杂查询条件
|
||||
const visibleMatcher = Matcher.all(PositionComponent, RenderComponent)
|
||||
.none(HiddenComponent);
|
||||
|
||||
// 通过QuerySystem执行查询
|
||||
const visibleEntities = querySystem.query(visibleMatcher.getCondition());
|
||||
|
||||
// 过滤和排序需要手动处理
|
||||
const sortedEntities = visibleEntities.entities
|
||||
.filter(entity => entity.name.startsWith('Boss'))
|
||||
.orderBy((a, b) => a.id - b.id);
|
||||
.sort((a, b) => a.id - b.id)
|
||||
.slice(0, 10); // 限制数量
|
||||
|
||||
// 迭代结果
|
||||
visibleEnemies.forEach((entity, index) => {
|
||||
sortedEntities.forEach((entity, index) => {
|
||||
console.log(`敌人 ${index}: ${entity.name}`);
|
||||
});
|
||||
```
|
||||
@@ -87,31 +95,32 @@ visibleEnemies.forEach((entity, index) => {
|
||||
### 5. 高级查询功能
|
||||
|
||||
```typescript
|
||||
// 复合查询
|
||||
const complexResult = querySystem.queryComplex(
|
||||
{
|
||||
type: QueryConditionType.ALL,
|
||||
componentTypes: [PositionComponent, VelocityComponent],
|
||||
mask: /* 位掩码 */
|
||||
},
|
||||
{
|
||||
type: QueryConditionType.NONE,
|
||||
componentTypes: [DeadComponent],
|
||||
mask: /* 位掩码 */
|
||||
}
|
||||
// QuerySystem主要提供基础查询方法
|
||||
// 复杂查询推荐使用Matcher和EntitySystem
|
||||
|
||||
// 基本查询
|
||||
const positionResult = querySystem.queryAll(PositionComponent, VelocityComponent);
|
||||
const healthResult = querySystem.queryAll(HealthComponent);
|
||||
const manaResult = querySystem.queryAll(ManaComponent);
|
||||
|
||||
// 排除死亡实体的移动实体
|
||||
const aliveMovingEntities = positionResult.entities.filter(entity =>
|
||||
!entity.hasComponent(DeadComponent)
|
||||
);
|
||||
|
||||
// 批量查询
|
||||
const batchResults = querySystem.batchQuery([
|
||||
{ type: QueryConditionType.ALL, componentTypes: [HealthComponent], mask: /* 位掩码 */ },
|
||||
{ type: QueryConditionType.ALL, componentTypes: [ManaComponent], mask: /* 位掩码 */ }
|
||||
]);
|
||||
|
||||
// 并行查询
|
||||
const parallelResults = await querySystem.parallelQuery([
|
||||
{ type: QueryConditionType.ALL, componentTypes: [PositionComponent], mask: /* 位掩码 */ },
|
||||
{ type: QueryConditionType.ALL, componentTypes: [VelocityComponent], mask: /* 位掩码 */ }
|
||||
]);
|
||||
// 如果需要复杂查询,推荐在EntitySystem中使用Matcher
|
||||
class ComplexQuerySystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.all(PositionComponent, VelocityComponent).none(DeadComponent));
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// entities已经是过滤后的结果
|
||||
for (const entity of entities) {
|
||||
// 处理逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 场景级别的实体查询
|
||||
@@ -147,12 +156,9 @@ querySystem.setCacheConfig(200, 2000); // 最大200个缓存项,2秒超时
|
||||
// 清空缓存
|
||||
querySystem.clearCache();
|
||||
|
||||
// 预热常用查询
|
||||
const commonQueries = [
|
||||
{ type: QueryConditionType.ALL, componentTypes: [PositionComponent], mask: /* 位掩码 */ },
|
||||
{ type: QueryConditionType.ALL, componentTypes: [VelocityComponent], mask: /* 位掩码 */ }
|
||||
];
|
||||
querySystem.warmUpCache(commonQueries);
|
||||
// 预热常用查询(使用基础查询方法)
|
||||
querySystem.queryAll(PositionComponent); // 预热Position查询
|
||||
querySystem.queryAll(VelocityComponent); // 预热Velocity查询
|
||||
```
|
||||
|
||||
### 2. 索引优化
|
||||
@@ -171,52 +177,101 @@ console.log(report);
|
||||
### 3. 查询监听和快照
|
||||
|
||||
```typescript
|
||||
// 监听查询结果变更
|
||||
const unwatch = querySystem.watchQuery(
|
||||
{ type: QueryConditionType.ALL, componentTypes: [EnemyComponent], mask: /* 位掩码 */ },
|
||||
(entities, changeType) => {
|
||||
console.log(`敌人实体${changeType}: ${entities.length}个`);
|
||||
// QuerySystem主要用于基础查询,高级功能请使用EntitySystem和事件系统
|
||||
|
||||
// 如需监听实体变化,使用事件系统
|
||||
scene.entityManager.eventBus.on('entity:added', (entity) => {
|
||||
if (entity.hasComponent(EnemyComponent)) {
|
||||
console.log('新增敌人实体');
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// 取消监听
|
||||
unwatch();
|
||||
scene.entityManager.eventBus.on('entity:removed', (entity) => {
|
||||
if (entity.hasComponent(EnemyComponent)) {
|
||||
console.log('移除敌人实体');
|
||||
}
|
||||
});
|
||||
|
||||
// 创建查询快照
|
||||
const snapshot1 = querySystem.createSnapshot(
|
||||
{ type: QueryConditionType.ALL, componentTypes: [PlayerComponent], mask: /* 位掩码 */ }
|
||||
);
|
||||
|
||||
// 稍后创建另一个快照
|
||||
const snapshot2 = querySystem.createSnapshot(
|
||||
{ type: QueryConditionType.ALL, componentTypes: [PlayerComponent], mask: /* 位掩码 */ }
|
||||
);
|
||||
// 手动创建快照进行比较
|
||||
const snapshot1 = querySystem.queryAll(PlayerComponent).entities.map(e => e.id);
|
||||
// 稍后
|
||||
const snapshot2 = querySystem.queryAll(PlayerComponent).entities.map(e => e.id);
|
||||
|
||||
// 比较快照
|
||||
const diff = querySystem.compareSnapshots(snapshot1, snapshot2);
|
||||
console.log(`新增: ${diff.added.length}, 移除: ${diff.removed.length}`);
|
||||
const added = snapshot2.filter(id => !snapshot1.includes(id));
|
||||
const removed = snapshot1.filter(id => !snapshot2.includes(id));
|
||||
console.log(`新增: ${added.length}, 移除: ${removed.length}`);
|
||||
```
|
||||
|
||||
## 实际使用示例
|
||||
## 使用Matcher进行高级查询
|
||||
|
||||
### 移动系统示例
|
||||
Matcher是一个优雅的查询封装器,提供流畅的API和强大的缓存机制。
|
||||
|
||||
### 基本Matcher用法
|
||||
|
||||
```typescript
|
||||
import { Matcher } from '@esengine/ecs-framework';
|
||||
|
||||
// 创建Matcher查询条件
|
||||
const movingMatcher = Matcher.all(PositionComponent, VelocityComponent);
|
||||
// 在QuerySystem中需要使用基础查询方法
|
||||
const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityComponent).entities;
|
||||
|
||||
// 复合查询需要使用EntitySystem或手动过滤
|
||||
const aliveEnemiesMatcher = Matcher.all(EnemyComponent, HealthComponent)
|
||||
.any(WeaponComponent, MagicComponent)
|
||||
.none(DeadComponent, StunnedComponent);
|
||||
|
||||
// 在EntitySystem中使用
|
||||
class AliveEnemySystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(aliveEnemiesMatcher);
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// entities已经是匹配的实体
|
||||
for (const entity of entities) {
|
||||
// 处理存活的敌人
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 或者手动过滤
|
||||
const enemyResult = scene.querySystem.queryAll(EnemyComponent, HealthComponent);
|
||||
const aliveEnemies = enemyResult.entities.filter(entity => {
|
||||
const hasWeaponOrMagic = entity.hasComponent(WeaponComponent) || entity.hasComponent(MagicComponent);
|
||||
const isAlive = !entity.hasComponent(DeadComponent) && !entity.hasComponent(StunnedComponent);
|
||||
return hasWeaponOrMagic && isAlive;
|
||||
});
|
||||
|
||||
// 单个实体检查
|
||||
const playerResult = scene.querySystem.queryAll(PlayerComponent);
|
||||
if (playerResult.entities.includes(someEntity)) {
|
||||
console.log('这是玩家实体');
|
||||
}
|
||||
|
||||
// 统计信息
|
||||
console.log(`玩家数量: ${playerResult.count}`);
|
||||
console.log(`是否有玩家: ${playerResult.count > 0}`);
|
||||
```
|
||||
|
||||
### 系统中使用Matcher
|
||||
|
||||
```typescript
|
||||
import { EntitySystem, Entity, Matcher } from '@esengine/ecs-framework';
|
||||
|
||||
class MovementSystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.empty().all(PositionComponent, VelocityComponent));
|
||||
// 在构造函数中直接传入Matcher
|
||||
super(Matcher.all(PositionComponent, VelocityComponent));
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// 查询所有可移动的实体
|
||||
const movableEntities = this.scene.querySystem.queryTwoComponents(
|
||||
PositionComponent,
|
||||
VelocityComponent
|
||||
);
|
||||
|
||||
movableEntities.forEach(({ entity, component1: position, component2: velocity }) => {
|
||||
// entities参数已经是系统自动过滤后的实体
|
||||
for (const entity of entities) {
|
||||
const position = entity.getComponent(PositionComponent)!;
|
||||
const velocity = entity.getComponent(VelocityComponent)!;
|
||||
|
||||
// 更新位置
|
||||
position.x += velocity.x * Time.deltaTime;
|
||||
position.y += velocity.y * Time.deltaTime;
|
||||
@@ -228,7 +283,7 @@ class MovementSystem extends EntitySystem {
|
||||
if (position.y < 0 || position.y > 600) {
|
||||
velocity.y = -velocity.y;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -238,15 +293,13 @@ class MovementSystem extends EntitySystem {
|
||||
```typescript
|
||||
class CollisionSystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.empty().all(PositionComponent, ColliderComponent));
|
||||
// 在构造函数中传入Matcher
|
||||
super(Matcher.all(PositionComponent, ColliderComponent));
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// 获取所有具有碰撞器的实体
|
||||
const collidableEntities = this.scene.querySystem.queryTwoComponents(
|
||||
PositionComponent,
|
||||
ColliderComponent
|
||||
);
|
||||
// entities已经是匹配的实体
|
||||
const collidableEntities = entities;
|
||||
|
||||
// 检测碰撞
|
||||
for (let i = 0; i < collidableEntities.length; i++) {
|
||||
@@ -255,16 +308,15 @@ class CollisionSystem extends EntitySystem {
|
||||
const entityB = collidableEntities[j];
|
||||
|
||||
if (this.checkCollision(entityA, entityB)) {
|
||||
this.handleCollision(entityA.entity, entityB.entity);
|
||||
this.handleCollision(entityA, entityB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private checkCollision(entityA: any, entityB: any): boolean {
|
||||
// 简单的距离检测
|
||||
const posA = entityA.component1;
|
||||
const posB = entityB.component1;
|
||||
private checkCollision(entityA: Entity, entityB: Entity): boolean {
|
||||
const posA = entityA.getComponent(PositionComponent)!;
|
||||
const posB = entityB.getComponent(PositionComponent)!;
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(posA.x - posB.x, 2) + Math.pow(posA.y - posB.y, 2)
|
||||
);
|
||||
@@ -282,20 +334,23 @@ class CollisionSystem extends EntitySystem {
|
||||
```typescript
|
||||
class HealthSystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.empty().all(HealthComponent));
|
||||
// 在构造函数中传入Matcher
|
||||
super(Matcher.all(HealthComponent));
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// 查询所有具有生命值的实体
|
||||
const healthEntities = this.scene.querySystem.queryComponentTyped(HealthComponent);
|
||||
// entities已经是匹配的实体
|
||||
const healthEntities = entities;
|
||||
const deadEntities: Entity[] = [];
|
||||
|
||||
healthEntities.forEach(({ entity, component: health }) => {
|
||||
for (const entity of healthEntities) {
|
||||
const health = entity.getComponent(HealthComponent)!;
|
||||
|
||||
// 检查死亡
|
||||
if (health.currentHealth <= 0) {
|
||||
deadEntities.push(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 移除死亡实体
|
||||
deadEntities.forEach(entity => {
|
||||
@@ -306,28 +361,286 @@ class HealthSystem extends EntitySystem {
|
||||
}
|
||||
```
|
||||
|
||||
### Matcher完整API参考
|
||||
|
||||
#### 静态创建方法
|
||||
|
||||
```typescript
|
||||
// 基础静态方法
|
||||
const allMatcher = Matcher.all(PositionComponent, VelocityComponent); // 必须包含所有组件
|
||||
const anyMatcher = Matcher.any(WeaponComponent, MagicComponent); // 必须包含任意一个组件
|
||||
const noneMatcher = Matcher.none(DeadComponent, DisabledComponent); // 不能包含任何指定组件
|
||||
|
||||
// 特殊查询静态方法
|
||||
const tagMatcher = Matcher.byTag(1); // 按标签查询
|
||||
const nameMatcher = Matcher.byName("Player"); // 按名称查询
|
||||
const componentMatcher = Matcher.byComponent(HealthComponent); // 单组件查询
|
||||
|
||||
// 构建器方法
|
||||
const complexMatcher = Matcher.complex(); // 创建复杂查询构建器
|
||||
const emptyMatcher = Matcher.empty(); // 创建空匹配器
|
||||
```
|
||||
|
||||
#### 实例方法 - 条件构建
|
||||
|
||||
```typescript
|
||||
// 基础条件方法
|
||||
const matcher = Matcher.empty()
|
||||
.all(PositionComponent, VelocityComponent) // 必须包含所有组件
|
||||
.any(WeaponComponent, MagicComponent) // 必须包含任意一个组件
|
||||
.none(DeadComponent, StunnedComponent); // 不能包含任何指定组件
|
||||
|
||||
// 别名方法(提供更语义化的API)
|
||||
const semanticMatcher = Matcher.empty()
|
||||
.all(PositionComponent)
|
||||
.exclude(DeadComponent) // exclude() 等同于 none()
|
||||
.one(WeaponComponent, MagicComponent); // one() 等同于 any()
|
||||
|
||||
// 特殊条件方法
|
||||
const advancedMatcher = Matcher.empty()
|
||||
.all(EnemyComponent)
|
||||
.withTag(2) // 指定标签
|
||||
.withName("Boss") // 指定名称
|
||||
.withComponent(HealthComponent); // 单组件条件
|
||||
```
|
||||
|
||||
#### 条件移除方法
|
||||
|
||||
```typescript
|
||||
// 移除特殊条件
|
||||
const matcher = Matcher.byTag(1)
|
||||
.withName("Player")
|
||||
.withComponent(HealthComponent);
|
||||
|
||||
// 移除各种条件
|
||||
matcher.withoutTag(); // 移除标签条件
|
||||
matcher.withoutName(); // 移除名称条件
|
||||
matcher.withoutComponent(); // 移除单组件条件
|
||||
```
|
||||
|
||||
#### 实用工具方法
|
||||
|
||||
```typescript
|
||||
// 检查和调试
|
||||
const matcher = Matcher.all(PositionComponent, VelocityComponent)
|
||||
.none(DeadComponent);
|
||||
|
||||
// 检查是否为空条件
|
||||
if (matcher.isEmpty()) {
|
||||
console.log('匹配器没有设置任何条件');
|
||||
}
|
||||
|
||||
// 获取条件信息(只读)
|
||||
const condition = matcher.getCondition();
|
||||
console.log('必须组件:', condition.all.map(c => c.name));
|
||||
console.log('任选组件:', condition.any.map(c => c.name));
|
||||
console.log('排除组件:', condition.none.map(c => c.name));
|
||||
console.log('标签:', condition.tag);
|
||||
console.log('名称:', condition.name);
|
||||
console.log('单组件:', condition.component?.name);
|
||||
|
||||
// 调试输出
|
||||
console.log('匹配器描述:', matcher.toString());
|
||||
// 输出: "Matcher[all(PositionComponent, VelocityComponent) & none(DeadComponent)]"
|
||||
```
|
||||
|
||||
#### 克隆和重置
|
||||
|
||||
```typescript
|
||||
// 克隆匹配器
|
||||
const baseMatcher = Matcher.all(PositionComponent);
|
||||
const livingMatcher = baseMatcher.clone().all(HealthComponent).none(DeadComponent);
|
||||
const deadMatcher = baseMatcher.clone().all(DeadComponent);
|
||||
|
||||
// 重置匹配器
|
||||
const reusableMatcher = Matcher.all(PositionComponent);
|
||||
console.log(reusableMatcher.toString()); // "Matcher[all(PositionComponent)]"
|
||||
|
||||
reusableMatcher.reset(); // 清空所有条件
|
||||
console.log(reusableMatcher.toString()); // "Matcher[]"
|
||||
|
||||
reusableMatcher.all(PlayerComponent); // 重新设置条件
|
||||
console.log(reusableMatcher.toString()); // "Matcher[all(PlayerComponent)]"
|
||||
```
|
||||
|
||||
#### 链式调用示例
|
||||
|
||||
```typescript
|
||||
// 复杂的链式调用
|
||||
const complexMatcher = Matcher.empty()
|
||||
.all(PositionComponent, RenderComponent) // 必须有位置和渲染组件
|
||||
.any(PlayerComponent, NPCComponent) // 必须是玩家或NPC
|
||||
.none(DeadComponent, HiddenComponent) // 不能死亡或隐藏
|
||||
.withTag(1) // 标签为1
|
||||
.exclude(DisabledComponent); // 不能被禁用
|
||||
|
||||
// 在EntitySystem中使用
|
||||
class VisibleCharacterSystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(complexMatcher);
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// entities已经是符合所有条件的实体
|
||||
for (const entity of entities) {
|
||||
// 处理可见角色的逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 查询优化
|
||||
### 1. Matcher使用建议
|
||||
|
||||
- 尽量使用类型安全的查询方法
|
||||
- 避免在每帧都创建新的查询
|
||||
- 合理使用缓存机制
|
||||
```typescript
|
||||
// 推荐的用法:
|
||||
const matcher = Matcher.all(Position, Velocity);
|
||||
|
||||
### 2. 性能监控
|
||||
// 在系统中使用
|
||||
class MySystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.all(RequiredComponent));
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// entities已经是系统自动过滤的结果
|
||||
for (const entity of entities) {
|
||||
// 处理逻辑...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- 定期检查查询性能报告
|
||||
// 避免在process方法中重复查询
|
||||
class InefficientSystem extends EntitySystem {
|
||||
protected process(entities: Entity[]): void {
|
||||
// 不必要的额外查询,性能差
|
||||
const condition = Matcher.all(RequiredComponent).getCondition();
|
||||
const result = this.scene.querySystem.query(condition);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Matcher API最佳实践
|
||||
|
||||
#### 选择合适的创建方式
|
||||
|
||||
```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)
|
||||
.none(DeadComponent);
|
||||
|
||||
// ❌ 不推荐:简单条件使用复杂语法
|
||||
const simpleButBad = Matcher.empty().all(PositionComponent);
|
||||
// 应该用: Matcher.all(PositionComponent)
|
||||
```
|
||||
|
||||
#### 合理使用别名方法
|
||||
|
||||
```typescript
|
||||
// 使用语义化的别名提高可读性
|
||||
const combatUnits = Matcher.all(PositionComponent, HealthComponent)
|
||||
.one(WeaponComponent, MagicComponent) // one() 比 any() 更语义化
|
||||
.exclude(DeadComponent, PacifistComponent); // exclude() 比 none() 更直观
|
||||
```
|
||||
|
||||
#### 合理的克隆和重用
|
||||
|
||||
```typescript
|
||||
// ✅ 推荐:基础匹配器重用
|
||||
const livingEntityMatcher = Matcher.all(HealthComponent).none(DeadComponent);
|
||||
const livingPlayerMatcher = livingEntityMatcher.clone().all(PlayerComponent);
|
||||
const livingEnemyMatcher = livingEntityMatcher.clone().all(EnemyComponent);
|
||||
|
||||
// ✅ 推荐:重置匹配器重用
|
||||
const reusableMatcher = Matcher.empty();
|
||||
|
||||
// 用于玩家系统
|
||||
reusableMatcher.reset().all(PlayerComponent);
|
||||
const playerSystem = new PlayerSystem(reusableMatcher.clone());
|
||||
|
||||
// 用于敌人系统
|
||||
reusableMatcher.reset().all(EnemyComponent);
|
||||
const enemySystem = new EnemySystem(reusableMatcher.clone());
|
||||
```
|
||||
|
||||
#### 调试和维护
|
||||
|
||||
```typescript
|
||||
// 在开发阶段添加调试信息
|
||||
const debugMatcher = Matcher.all(ComplexComponent)
|
||||
.any(VariantA, VariantB)
|
||||
.none(DisabledComponent);
|
||||
|
||||
if (DEBUG_MODE) {
|
||||
console.log('系统匹配条件:', debugMatcher.toString());
|
||||
const condition = debugMatcher.getCondition();
|
||||
console.log('预期匹配实体数:',
|
||||
scene.querySystem.queryAll(...condition.all).count);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 查询优化
|
||||
|
||||
- **使用Matcher封装复杂查询**:提供更好的可读性和缓存
|
||||
- **避免频繁创建查询**:在系统初始化时创建,重复使用
|
||||
- **合理使用any()和none()条件**:减少不必要的实体遍历
|
||||
- **利用Matcher的缓存机制**:自动优化重复查询性能
|
||||
- **使用克隆方法复用基础条件**:避免重复定义相似的匹配条件
|
||||
- **选择合适的静态方法**:单一条件优先使用对应的静态方法
|
||||
|
||||
### 3. 性能监控
|
||||
|
||||
- 定期检查查询性能报告
|
||||
- 监控缓存命中率
|
||||
- 优化频繁使用的查询
|
||||
- 使用性能测试验证优化效果
|
||||
|
||||
### 3. 内存管理
|
||||
### 4. 内存管理
|
||||
|
||||
- 及时清理不需要的查询监听器
|
||||
- 合理设置缓存大小
|
||||
- 避免创建过多的查询快照
|
||||
- 适当使用Matcher的clone()和reset()方法
|
||||
|
||||
### 4. 代码组织
|
||||
### 5. 代码组织
|
||||
|
||||
- 将复杂查询封装到专门的方法中
|
||||
- 使用查询构建器创建可读性更好的查询
|
||||
- 在系统中合理组织查询逻辑
|
||||
- **系统级别的Matcher**:在系统中创建和管理Matcher
|
||||
- **查询逻辑封装**:将复杂查询封装到专门的方法中
|
||||
- **条件复用**:使用clone()方法复用基础查询条件
|
||||
- **清晰的命名**:给Matcher变量使用描述性的名称
|
||||
|
||||
### 6. 迁移指南
|
||||
|
||||
系统中Matcher的推荐用法:
|
||||
|
||||
```typescript
|
||||
// 在EntitySystem中使用Matcher
|
||||
class MySystem extends EntitySystem {
|
||||
constructor() {
|
||||
super(Matcher.all(ComponentA, ComponentB).none(ComponentC));
|
||||
}
|
||||
|
||||
protected process(entities: Entity[]): void {
|
||||
// entities已经是系统自动过滤的结果
|
||||
for (const entity of entities) {
|
||||
// 处理逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 使用最佳实践
|
||||
|
||||
- 在EntitySystem构造函数中传入Matcher
|
||||
- 使用`none()`来排除组件
|
||||
- 使用`any()`来匹配任意组件
|
||||
- 直接使用EntitySystem的entities参数,避免额外查询
|
||||
- 定期检查查询性能和缓存命中率
|
||||
Reference in New Issue
Block a user