refactor(hero): 优化英雄对象池管理及视图初始化

- 在Monster类中实现多键对象池管理,提升英雄节点复用效率
- 将HeroViewComp的初始化逻辑提取到独立init方法,便于对象池复用时重置状态
- 移除HeroSpine中冗余的onDestroy方法
- 修复HeroViewComp中方向缩放计算问题,确保scale.x为正
- 优化碰撞体启用逻辑,延迟一帧确保物理系统正确注册
- 清理HeroViewComp中残留的定时器和缓动
This commit is contained in:
walkpan
2026-01-02 23:27:05 +08:00
parent 2c7a628921
commit 81f55a796d
4 changed files with 77 additions and 22 deletions

View File

@@ -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<prefabPath, NodePool>
static pools: Map<string, NodePool> = 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<ecs.Comp>(
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)
// 初始化移动参数,包括线路和生成顺序