fix: 收敛战斗内存增长并强化战斗结束清理

This commit is contained in:
panw
2026-03-18 16:46:52 +08:00
parent 56227d8f3f
commit 035066752c
7 changed files with 155 additions and 58 deletions

View File

@@ -59,6 +59,7 @@ export class HeroViewComp extends CCComp {
}> = [];
private isProcessingDamage: boolean = false;
private damageInterval: number = 0.01; // 伤害数字显示间隔
private effectLifeTime: number = 0.8;
onLoad() {
this.as = this.getComponent(HeroSpine);
const collider = this.node.getComponent(BoxCollider2D);
@@ -206,28 +207,19 @@ export class HeroViewComp extends CCComp {
/** 升级特效 */
private lv_up() {
var path = "game/skill/buff/buff_lvup";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect("game/skill/buff/buff_lvup", this.node, 1.0);
}
/** 攻击力提升特效 */
private ap_up() {
var path = "game/skill/buff/buff_apup";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect("game/skill/buff/buff_apup", this.node, 1.0);
}
/** 显示 Buff 特效 */
private show_do_buff(name: string) {
var path = "game/skill/buff/" + name;
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
let pos = v3(this.node.position.x, this.node.position.y + 20, this.node.position.z);
node.parent = this.node.parent;
node.setPosition(pos);
this.spawnEffect(path, this.node.parent, 1.0, pos);
}
@@ -244,24 +236,22 @@ export class HeroViewComp extends CCComp {
/** 冰冻特效 */
private in_iced(t: number = 1, ap: number = 0) {
var path = "game/skill/buff/buff_iced";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.getComponent(timedCom).time = t;
node.getComponent(timedCom).ap = ap;
node.parent = this.node;
const node = this.spawnEffect("game/skill/buff/buff_iced", this.node, t);
if (!node) return;
const timer = node.getComponent(timedCom) || node.addComponent(timedCom);
timer.time = t;
timer.ap = ap;
}
/** 眩晕特效 */
private in_yun(t: number = 1, ap: number = 0) {
var path = "game/skill/buff/buff_yun";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
const node = this.spawnEffect("game/skill/buff/buff_yun", this.node, t);
if (!node) return;
let height = this.node.getComponent(UITransform).height;
node.setPosition(v3(0, height));
node.getComponent(timedCom).time = t;
node.getComponent(timedCom).ap = ap;
node.parent = this.node;
const timer = node.getComponent(timedCom) || node.addComponent(timedCom);
timer.time = t;
timer.ap = ap;
}
/** 技能提示 */
@@ -294,39 +284,42 @@ export class HeroViewComp extends CCComp {
public palayBuff(anm: string = ""){
if(anm==="") return;
var path = "game/skill/buff/" + anm;
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect(path, this.node, this.effectLifeTime);
}
public playReady(anm: string = ""){
if(anm==="") return;
var path = "game/skill/ready/" + anm;
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect(path, this.node, this.effectLifeTime);
}
public playEnd(anm: string = ""){
if(anm==="") return;
var path = "game/skill/end/" + anm;
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect(path, this.node, this.effectLifeTime);
}
/** 治疗特效 */
private heathed() {
var path = "game/skill/buff/heathed";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect("game/skill/buff/heathed", this.node, 1.0);
}
private deaded(){
var path = "game/skill/end/atked";
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
node.parent = this.node;
this.spawnEffect("game/skill/end/atked", this.node, this.effectLifeTime);
}
private spawnEffect(path: string, parent: Node | null, life: number = 0.8, worldPos?: Vec3): Node | null {
if (!parent || !parent.isValid) return null;
const prefab: Prefab = oops.res.get(path, Prefab)!;
if (!prefab) return null;
const node = instantiate(prefab);
if (!node || !node.isValid) return null;
node.parent = parent;
if (worldPos) {
node.setWorldPosition(worldPos);
}
const timer = node.getComponent(timedCom) || node.addComponent(timedCom);
timer.time = Math.max(0.2, life);
timer.ap = 0;
return node;
}
// 注意BaseUp 逻辑已移到 HeroAttrSystem.update()
// 注意updateTemporaryBuffsDebuffs 逻辑已移到 HeroAttrSystem.update()

View File

@@ -19,7 +19,15 @@ export class Monster extends ecs.Entity {
// 多键对象池Map<prefabPath, NodePool>
static pools: Map<string, NodePool> = new Map();
static readonly MAX_POOL_SIZE: number = 24;
static readonly MAX_POOL_SIZE: number = 12;
static readonly MAX_POOL_TOTAL: number = 60;
private static totalPoolSize(): number {
let total = 0;
this.pools.forEach((pool) => {
total += pool.size();
});
return total;
}
static getFromPool(path: string): Node | null {
if (this.pools.has(path)) {
@@ -40,7 +48,7 @@ export class Monster extends ecs.Entity {
this.pools.set(path, new NodePool());
}
const pool = this.pools.get(path)!;
if (pool.size() >= this.MAX_POOL_SIZE) {
if (pool.size() >= this.MAX_POOL_SIZE || this.totalPoolSize() >= this.MAX_POOL_TOTAL) {
node.destroy();
return;
}
@@ -49,6 +57,12 @@ export class Monster extends ecs.Entity {
static clearPools() {
this.pools.forEach((pool) => {
while (pool.size() > 0) {
const node = pool.get();
if (node && node.isValid) {
node.destroy();
}
}
pool.clear();
});
this.pools.clear();
@@ -62,7 +76,8 @@ export class Monster extends ecs.Entity {
return {
paths: this.pools.size,
total,
maxPerPath: this.MAX_POOL_SIZE
maxPerPath: this.MAX_POOL_SIZE,
maxTotal: this.MAX_POOL_TOTAL
};
}

View File

@@ -44,7 +44,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
private readonly attackPassThresholdX = 60;
private readonly minSpacingY = 30;
private readonly renderSortInterval = 0.05;
private renderSortElapsed = 0;
private lastRenderSortAt = 0;
private heroMoveMatcher: ecs.IMatcher | null = null;
private heroViewMatcher: ecs.IMatcher | null = null;
private readonly renderEntries: { node: Node; bossPriority: number; frontScore: number; spawnOrder: number; eid: number }[] = [];
@@ -405,7 +405,6 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
}
private updateRenderOrder(view: HeroViewComp) {
this.renderSortElapsed += this.dt;
const scene = smc.map?.MapView?.scene;
const actorRoot = scene?.entityLayer?.node?.getChildByName("HERO");
if (!actorRoot) return;
@@ -414,8 +413,9 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
view.node.parent = actorRoot;
}
if (this.renderSortElapsed < this.renderSortInterval) return;
this.renderSortElapsed = 0;
const now = Date.now() / 1000;
if (now - this.lastRenderSortAt < this.renderSortInterval) return;
this.lastRenderSortAt = now;
this.renderEntryCount = 0;
ecs.query(this.getHeroMoveMatcher()).forEach(e => {

View File

@@ -25,9 +25,16 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
debugMode: boolean = false; // 是否启用调试模式
private readonly emptyCastPlan = { skillId: 0, isFriendly: false, targetPos: null as Vec3 | null, targetEids: [] as number[] };
private readonly meleeCastRange = 64;
private heroMatcher: ecs.IMatcher | null = null;
private getHeroMatcher(): ecs.IMatcher {
if (!this.heroMatcher) {
this.heroMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp);
}
return this.heroMatcher;
}
filter(): ecs.IMatcher {
return ecs.allOf(HeroAttrsComp, HeroViewComp);
return this.getHeroMatcher();
}
update(e: ecs.Entity): void {
@@ -181,7 +188,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const currentX = heroView.node.position.x;
let nearest: HeroViewComp | null = null;
let minDist = Infinity;
ecs.query(this.filter()).forEach(entity => {
ecs.query(this.getHeroMatcher()).forEach(entity => {
const attrs = entity.get(HeroAttrsComp);
const view = entity.get(HeroViewComp);
if (!attrs || !view?.node) return;