Files
esengine/source/src/ECS/Systems/EntitySystem.ts

320 lines
8.2 KiB
TypeScript
Raw Normal View History

import { Entity } from '../Entity';
import { Core } from '../../Core';
import { Matcher } from '../Utils/Matcher';
import { PerformanceMonitor } from '../../Utils/PerformanceMonitor';
import type { Scene } from '../Scene';
import type { ISystemBase } from '../../Types';
/**
*
*
* ECS架构中的逻辑处理单元
*
*
* @example
* ```typescript
* class MovementSystem extends EntitySystem {
* constructor() {
* super(Matcher.empty().all(Transform, Velocity));
* }
*
* protected process(entities: Entity[]): void {
* for (const entity of entities) {
* const transform = entity.getComponent(Transform);
* const velocity = entity.getComponent(Velocity);
* transform.position.add(velocity.value);
* }
* }
* }
* ```
*/
export abstract class EntitySystem implements ISystemBase {
private _entities: Entity[] = [];
private _updateOrder: number = 0;
private _enabled: boolean = true;
private _performanceMonitor = PerformanceMonitor.instance;
private _systemName: string;
/**
*
*/
public get entities(): readonly Entity[] {
return this._entities;
}
/**
*
*/
public get updateOrder(): number {
return this._updateOrder;
}
2021-08-28 21:26:44 +08:00
public set updateOrder(value: number) {
this.setUpdateOrder(value);
}
2021-08-28 21:26:44 +08:00
/**
*
*/
public get enabled(): boolean {
return this._enabled;
}
2020-06-08 18:26:05 +08:00
/**
*
*/
public set enabled(value: boolean) {
this._enabled = value;
}
/**
*
*/
public get systemName(): string {
return this._systemName;
}
2020-06-08 18:26:05 +08:00
constructor(matcher?: Matcher) {
this._matcher = matcher ? matcher : Matcher.empty();
this._systemName = this.constructor.name;
this.initialize();
}
2020-07-28 16:25:20 +08:00
private _scene!: Scene;
2020-06-08 18:26:05 +08:00
/**
*
*/
public get scene(): Scene {
return this._scene;
}
2020-06-08 18:26:05 +08:00
public set scene(value: Scene) {
this._scene = value;
this._entities = [];
}
2020-07-28 16:25:20 +08:00
private _matcher: Matcher;
2020-06-08 18:26:05 +08:00
/**
*
*/
public get matcher(): Matcher {
return this._matcher;
}
2021-04-07 15:24:37 +08:00
/**
*
* @param order
*/
public setUpdateOrder(order: number): void {
this._updateOrder = order;
this.scene.entityProcessors.setDirty();
}
2020-06-08 20:11:58 +08:00
/**
*
*
*
*/
public initialize(): void {
// 子类可以重写此方法
}
2020-06-08 20:11:58 +08:00
/**
*
*
*
*
* @param entity
*/
public onChanged(entity: Entity): void {
const contains = this._entities.includes(entity);
const interest = this._matcher.isInterestedEntity(entity);
2020-06-08 20:11:58 +08:00
if (interest && !contains) {
this.add(entity);
} else if (!interest && contains) {
this.remove(entity);
2020-07-23 11:00:46 +08:00
}
}
2020-06-08 20:11:58 +08:00
/**
*
*
* @param entity
*/
public add(entity: Entity): void {
if (!this._entities.includes(entity)) {
this._entities.push(entity);
2020-07-23 11:00:46 +08:00
this.onAdded(entity);
}
}
2020-06-08 20:11:58 +08:00
/**
*
*
*
*
* @param entity
*/
protected onAdded(entity: Entity): void {
// 子类可以重写此方法
}
2020-06-08 20:11:58 +08:00
/**
*
*
* @param entity
*/
public remove(entity: Entity): void {
const index = this._entities.indexOf(entity);
if (index !== -1) {
this._entities.splice(index, 1);
2020-07-23 11:00:46 +08:00
this.onRemoved(entity);
}
}
2020-06-08 20:11:58 +08:00
/**
*
*
*
*
* @param entity
*/
protected onRemoved(entity: Entity): void {
// 子类可以重写此方法
}
2020-06-08 18:26:05 +08:00
/**
*
*
*
*/
public update(): void {
if (!this._enabled || !this.checkProcessing()) {
return;
2020-07-23 11:00:46 +08:00
}
2020-06-08 18:26:05 +08:00
const startTime = this._performanceMonitor.startMonitoring(this._systemName);
try {
this.begin();
this.process(this._entities);
} finally {
this._performanceMonitor.endMonitoring(this._systemName, startTime, this._entities.length);
}
}
/**
*
*
* update方法执行完毕后调用
*/
public lateUpdate(): void {
if (!this._enabled || !this.checkProcessing()) {
return;
2021-04-07 15:24:37 +08:00
}
const startTime = this._performanceMonitor.startMonitoring(`${this._systemName}_Late`);
try {
this.lateProcess(this._entities);
this.end();
} finally {
this._performanceMonitor.endMonitoring(`${this._systemName}_Late`, startTime, this._entities.length);
}
}
/**
*
*
*
*/
protected begin(): void {
// 子类可以重写此方法
}
/**
*
*
*
*
* @param entities
*/
protected process(entities: Entity[]): void {
// 子类必须实现此方法
}
2021-04-07 15:24:37 +08:00
/**
*
*
*
*
* @param entities
*/
protected lateProcess(entities: Entity[]): void {
// 子类可以重写此方法
}
/**
*
*
*
*/
protected end(): void {
// 子类可以重写此方法
}
/**
*
*
*
*
*
* @returns truefalse
*/
protected checkProcessing(): boolean {
return true;
}
/**
*
*
* @returns undefined
*/
public getPerformanceData() {
return this._performanceMonitor.getSystemData(this._systemName);
}
/**
*
*
* @returns undefined
*/
public getPerformanceStats() {
return this._performanceMonitor.getSystemStats(this._systemName);
}
/**
*
*/
public resetPerformanceData(): void {
this._performanceMonitor.resetSystem(this._systemName);
}
/**
*
*
* @returns
*/
public toString(): string {
const entityCount = this._entities.length;
const perfData = this.getPerformanceData();
const perfInfo = perfData ? ` (${perfData.executionTime.toFixed(2)}ms)` : '';
return `${this._systemName}[${entityCount} entities]${perfInfo}`;
2020-06-08 18:26:05 +08:00
}
2020-07-23 11:00:46 +08:00
}