From 81f55a796d3792db76fba8ab903cc8378960f1e9 Mon Sep 17 00:00:00 2001 From: walkpan Date: Fri, 2 Jan 2026 23:27:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor(hero):=20=E4=BC=98=E5=8C=96=E8=8B=B1?= =?UTF-8?q?=E9=9B=84=E5=AF=B9=E8=B1=A1=E6=B1=A0=E7=AE=A1=E7=90=86=E5=8F=8A?= =?UTF-8?q?=E8=A7=86=E5=9B=BE=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Monster类中实现多键对象池管理,提升英雄节点复用效率 - 将HeroViewComp的初始化逻辑提取到独立init方法,便于对象池复用时重置状态 - 移除HeroSpine中冗余的onDestroy方法 - 修复HeroViewComp中方向缩放计算问题,确保scale.x为正 - 优化碰撞体启用逻辑,延迟一帧确保物理系统正确注册 - 清理HeroViewComp中残留的定时器和缓动 --- assets/script/Main.ts | 10 ++--- assets/script/game/hero/HeroSpine.ts | 5 +-- assets/script/game/hero/HeroViewComp.ts | 26 +++++++---- assets/script/game/hero/Mon.ts | 58 ++++++++++++++++++++++--- 4 files changed, 77 insertions(+), 22 deletions(-) diff --git a/assets/script/Main.ts b/assets/script/Main.ts index bb5c2a5b..4cae125c 100644 --- a/assets/script/Main.ts +++ b/assets/script/Main.ts @@ -12,11 +12,11 @@ const { ccclass, property } = _decorator; @ccclass('Main') export class Main extends Root { start() { - // PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.Aabb - // |EPhysics2DDrawFlags.Pair - // |EPhysics2DDrawFlags.CenterOfMass - // |EPhysics2DDrawFlags.Joint - // |EPhysics2DDrawFlags.Shape; + PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.Aabb + |EPhysics2DDrawFlags.Pair + |EPhysics2DDrawFlags.CenterOfMass + |EPhysics2DDrawFlags.Joint + |EPhysics2DDrawFlags.Shape; } protected async run() { smc.initialize = ecs.getEntity(Initialize); diff --git a/assets/script/game/hero/HeroSpine.ts b/assets/script/game/hero/HeroSpine.ts index 54baf240..69cfa993 100644 --- a/assets/script/game/hero/HeroSpine.ts +++ b/assets/script/game/hero/HeroSpine.ts @@ -85,8 +85,5 @@ export class HeroSpine extends Component { this.status="move" this.anm.move() } - onDestroy() { - this.node.destroy(); - } - + } diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index 77c101b7..c444693c 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -1,4 +1,4 @@ -import { Vec3, _decorator , v3,Collider2D,Contact2DType,Label ,Node,Prefab,instantiate,ProgressBar, Component, Material, Sprite, math, clamp, Game, tween, Color, BoxCollider2D, UITransform} from "cc"; +import { Vec3, _decorator , v3,Collider2D,Contact2DType,Label ,Node,Prefab,instantiate,ProgressBar, Component, Material, Sprite, math, clamp, Game, tween, Tween, Color, BoxCollider2D, UITransform} from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { HeroSpine } from "./HeroSpine"; @@ -88,23 +88,29 @@ export class HeroViewComp extends CCComp { } /** 视图层逻辑代码分离演示 */ start () { + this.init(); + } + + /** 初始化/重置视图状态 */ + init() { this.as.idle() // 初始化 UI 节点 this.initUINodes(); /** 方向 */ - this.node.setScale(this.scale*this.node.scale.x,1*this.node.scale.y); + this.node.setScale(this.scale*Math.abs(this.node.scale.x), 1*this.node.scale.y); // 确保 scale.x 为正后再乘方向 this.top_node.setScale(this.scale*this.top_node.scale.x,1*this.top_node.scale.y); /* 显示角色血*/ this.top_node.getChildByName("hp").active = true; // 🔥 怪物不显示蓝条 - this.top_node.getChildByName("mp").active = this.model.fac === FacSet.HERO; + if (this.model) { + this.top_node.getChildByName("mp").active = this.model.fac === FacSet.HERO; + } this.top_node.getChildByName("shield").active = false; // 初始隐藏血条(有更新时才显示) this.top_node.active = false; - } /** 初始化 UI 节点引用 */ @@ -513,6 +519,10 @@ export class HeroViewComp extends CCComp { } } reset() { + // 清理残留的定时器和缓动 + this.unscheduleAllCallbacks(); + Tween.stopAllByTarget(this.node); + // 清理碰撞器事件监听 const collider = this.getComponent(Collider2D); if (collider) { @@ -525,10 +535,10 @@ export class HeroViewComp extends CCComp { this.damageQueue.length = 0; this.isProcessingDamage = false; - // 延迟销毁节点 - this.scheduleOnce(() => { - this.node.destroy(); - }, 0.1); + // 节点生命周期由 Monster 对象池管理,此处不再销毁 + // if (this.node && this.node.isValid) { + // this.node.destroy(); + // } } } diff --git a/assets/script/game/hero/Mon.ts b/assets/script/game/hero/Mon.ts index da134ce8..5c2b912d 100644 --- a/assets/script/game/hero/Mon.ts +++ b/assets/script/game/hero/Mon.ts @@ -1,4 +1,4 @@ -import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D} from "cc"; +import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D, NodePool} from "cc"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { smc } from "../common/SingletonModuleComp"; @@ -19,6 +19,26 @@ export class Monster extends ecs.Entity { HeroView!: HeroViewComp; MonMove!: MonMoveComp; + // 多键对象池:Map + static pools: Map = new Map(); + + static getFromPool(path: string): Node | null { + if (this.pools.has(path)) { + const pool = this.pools.get(path)!; + if (pool.size() > 0) { + return pool.get(); + } + } + return null; + } + + static putToPool(path: string, node: Node) { + if (!this.pools.has(path)) { + this.pools.set(path, new NodePool()); + } + this.pools.get(path)!.put(node); + } + protected init() { this.addComponents( MonMoveComp, @@ -28,6 +48,14 @@ export class Monster extends ecs.Entity { } destroy(): void { + // 回收节点到对象池 + const model = this.get(HeroAttrsComp); + const view = this.get(HeroViewComp); + if (model && view && view.node && view.node.isValid) { + const path = "game/heros/" + HeroInfo[model.hero_uuid].path; + Monster.putToPool(path, view.node); + } + this.remove(HeroViewComp); this.remove(HeroAttrsComp); this.remove(HeroSkillsComp); @@ -40,8 +68,14 @@ export class Monster extends ecs.Entity { let size=1 var scene = smc.map.MapView.scene; var path = "game/heros/"+HeroInfo[uuid].path; - var prefab: Prefab = oops.res.get(path, Prefab)!; - var node = instantiate(prefab); + + // 尝试从池中获取 + let node = Monster.getFromPool(path); + if (!node) { + var prefab: Prefab = oops.res.get(path, Prefab)!; + node = instantiate(prefab); + } + let LINE1=scene.entityLayer!.node!.getChildByName("LINE1")!; let LINE2=scene.entityLayer!.node!.getChildByName("LINE2")!; let LINE3=scene.entityLayer!.node!.getChildByName("LINE3")!; @@ -49,11 +83,22 @@ export class Monster extends ecs.Entity { // 🔥 设置初始 SiblingIndex - 防止溢出 const baseLane = lane === 0 ? LINE1 : lane === 1 ? LINE2 : lane === 2 ? LINE3 : LINE4; node.parent = baseLane + var view = node.getComponent(HeroViewComp)!; const collider = node.getComponent(BoxCollider2D); - if (collider) collider.enabled = false; // 先禁用 // 延迟一帧启用碰撞体 + if (collider) { + // 先禁用,下一帧启用,确保物理系统能正确注册新激活的节点 + collider.enabled = false; + view.scheduleOnce(() => { + if (node && node.isValid) { + collider.enabled = true; + collider.group = BoxSet.MONSTER; // 确保碰撞组正确 + collider.apply(); // 强制应用更改(如果需要) + } + }, 0); // 0延迟等于下一帧执行 + } + node.setScale(size*node.scale.x,size*node.scale.y); node.setPosition(pos) - var view = node.getComponent(HeroViewComp)!; const model = this.get(HeroAttrsComp); const skillsComp = this.get(HeroSkillsComp); let hero = HeroInfo[uuid]; // 共用英雄数据 @@ -87,6 +132,9 @@ export class Monster extends ecs.Entity { skillsComp.initSkills(hero.skills, uuid, this); this.add(view); + // 重置视图状态(对象池复用时必须) + view.init(); + oops.message.dispatchEvent("monster_load",this) // 初始化移动参数,包括线路和生成顺序