perf: 优化战斗系统内存与性能,增加对象池限制与内存监控面板

- 为Skill和Monster对象池添加最大容量限制(64/24),防止内存泄漏
- 实现DamageQueueComp的环形队列优化,减少数组操作开销
- 在MissionComp中添加内存监控面板,实时显示堆内存、实体数量、对象池状态
- 优化MoveSystem的渲染排序性能,缓存查询结果减少GC压力
- 调整角色控制器UI位置与样式,关闭调试日志减少性能开销
- 战斗结束时自动清理对象池,确保内存可回收
This commit is contained in:
panw
2026-03-16 18:49:43 +08:00
parent fb7b10b7e1
commit 5d24dbff29
8 changed files with 285 additions and 63 deletions

View File

@@ -41,6 +41,10 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
private readonly minSpacingY = 30;
private readonly renderSortInterval = 0.05;
private renderSortElapsed = 0;
private heroMoveMatcher: ecs.IMatcher | null = null;
private heroViewMatcher: ecs.IMatcher | null = null;
private readonly renderEntries: { node: Node; frontScore: number; spawnOrder: number; eid: number }[] = [];
private renderEntryCount = 0;
private readonly facConfigs: Record<number, MoveFacConfig> = {
[FacSet.HERO]: {
@@ -57,6 +61,20 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
}
};
private getHeroMoveMatcher(): ecs.IMatcher {
if (!this.heroMoveMatcher) {
this.heroMoveMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp, MoveComp);
}
return this.heroMoveMatcher;
}
private getHeroViewMatcher(): ecs.IMatcher {
if (!this.heroViewMatcher) {
this.heroViewMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp);
}
return this.heroViewMatcher;
}
filter(): ecs.IMatcher {
return ecs.allOf(MoveComp, HeroViewComp, HeroAttrsComp);
}
@@ -239,7 +257,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const selfPriority = selfAttrs ? this.getCombatPriority(selfAttrs) : 0;
let nearestAheadX = Infinity;
let nearestBehindX = -Infinity;
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp, MoveComp)).forEach(e => {
ecs.query(this.getHeroMoveMatcher()).forEach(e => {
if (e === self) return;
const attrs = e.get(HeroAttrsComp);
const view = e.get(HeroViewComp);
@@ -272,7 +290,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
private hasAnyActorTooClose(self: ecs.Entity, x: number, y: number): boolean {
const myAttrs = self.get(HeroAttrsComp);
if (!myAttrs) return false;
return ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => {
return ecs.query(this.getHeroViewMatcher()).some(e => {
if (e === self) return false;
const attrs = e.get(HeroAttrsComp);
if (!attrs || attrs.is_dead) return false;
@@ -303,7 +321,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
let minDis = Infinity;
// 优化查询:一次遍历
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => {
ecs.query(this.getHeroViewMatcher()).forEach(e => {
const m = e.get(HeroAttrsComp);
if (m.fac !== myFac && !m.is_dead) {
const v = e.get(HeroViewComp);
@@ -332,8 +350,8 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
if (this.renderSortElapsed < this.renderSortInterval) return;
this.renderSortElapsed = 0;
const renderList: { node: Node; frontScore: number; spawnOrder: number; eid: number }[] = [];
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp, MoveComp)).forEach(e => {
this.renderEntryCount = 0;
ecs.query(this.getHeroMoveMatcher()).forEach(e => {
const attrs = e.get(HeroAttrsComp);
const actorView = e.get(HeroViewComp);
const actorMove = e.get(MoveComp);
@@ -343,21 +361,27 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
actorView.node.parent = actorRoot;
}
const frontScore = attrs.fac === FacSet.HERO ? actorView.node.position.x : -actorView.node.position.x;
renderList.push({
node: actorView.node,
frontScore,
spawnOrder: actorMove.spawnOrder,
eid: e.eid
});
const entryIndex = this.renderEntryCount;
let entry = this.renderEntries[entryIndex];
if (!entry) {
entry = { node: actorView.node, frontScore: 0, spawnOrder: 0, eid: 0 };
this.renderEntries.push(entry);
}
entry.node = actorView.node;
entry.frontScore = frontScore;
entry.spawnOrder = actorMove.spawnOrder;
entry.eid = e.eid;
this.renderEntryCount += 1;
});
this.renderEntries.length = this.renderEntryCount;
renderList.sort((a, b) => {
this.renderEntries.sort((a, b) => {
if (a.frontScore !== b.frontScore) return a.frontScore - b.frontScore;
if (a.spawnOrder !== b.spawnOrder) return a.spawnOrder - b.spawnOrder;
return a.eid - b.eid;
});
renderList.forEach((item, index) => {
this.renderEntries.forEach((item, index) => {
item.node.setSiblingIndex(index);
});
}