From efe6cc0dd7dd43734e1dfa6750a37773a4b01959 Mon Sep 17 00:00:00 2001 From: pan Date: Thu, 4 Jun 2026 14:41:27 +0800 Subject: [PATCH] =?UTF-8?q?refactor(skill):=20=E9=87=8D=E6=9E=84=E6=8A=80?= =?UTF-8?q?=E8=83=BD=E7=9B=92=E5=AD=90=E7=AE=A1=E7=90=86=E4=B8=BAECS?= =?UTF-8?q?=E5=AE=9E=E4=BD=93=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增SBox ECS实体,统一管理技能盒子的创建、挂载与销毁 重构MissSkillsComp,改用SBox实体替代直接实例化技能节点 更新SkillBoxComp,新增实体引用以通过ECS生命周期销毁节点 临时调整SCastSystem的索敌范围为全屏级,方便测试 --- assets/script/game/hero/SCastSystem.ts | 1 + assets/script/game/map/MissSkillsComp.ts | 16 +++----- assets/script/game/map/SBox.ts | 52 ++++++++++++++++++++++++ assets/script/game/map/SBox.ts.meta | 9 ++++ assets/script/game/map/SkillBoxComp.ts | 34 +++++++++++++--- 5 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 assets/script/game/map/SBox.ts create mode 100644 assets/script/game/map/SBox.ts.meta diff --git a/assets/script/game/hero/SCastSystem.ts b/assets/script/game/hero/SCastSystem.ts index 3977164f..af587745 100644 --- a/assets/script/game/hero/SCastSystem.ts +++ b/assets/script/game/hero/SCastSystem.ts @@ -113,6 +113,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate mockAttrs.puncture_chance = 0; mockAttrs.fac = FacSet.HERO; mockAttrs.type = HType.Long; // 假定为远程,拥有较长索敌范围 + mockAttrs.dis = 2000; // 给予全屏以上的索敌范围 let targetPos: Vec3 | null = null; if (!isFriendly) { diff --git a/assets/script/game/map/MissSkillsComp.ts b/assets/script/game/map/MissSkillsComp.ts index 2e325443..055ac4da 100644 --- a/assets/script/game/map/MissSkillsComp.ts +++ b/assets/script/game/map/MissSkillsComp.ts @@ -25,6 +25,7 @@ import { _decorator, Node, Prefab, instantiate, Vec3 } 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 { SkillBoxComp } from "./SkillBoxComp"; +import { SBox } from "./SBox"; import { oops } from "db://oops-framework/core/Oops"; import { GameEvent } from "../common/config/GameEvent"; import { smc } from "../common/SingletonModuleComp"; @@ -164,9 +165,6 @@ export class MissSkillsComp extends CCComp { * @param card_lv 技能卡等级 */ addSkill(uuid: number, card_lv: number) { - // 技能节点的父容器 - var parent = smc.map.MapView.scene.entityLayer!.node!.getChildByName("SKILL")!; - if (!this.skill_box) { mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set"); return; @@ -179,17 +177,13 @@ export class MissSkillsComp extends CCComp { return; } - // 实例化并放入槽位 - const node = instantiate(this.skill_box); - node.parent = parent; - node.setPosition(new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0)); + // 使用 ECS 实体创建技能节点 + let sbox = ecs.getEntity(SBox); + let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0); + let node = sbox.load(uuid, card_lv, pos, this.skill_box); this.slots[emptyIndex].used = true; this.slots[emptyIndex].node = node; - - // 初始化技能效果组件 - const comp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp); - comp.init(uuid, card_lv); } /** ECS 组件移除时销毁节点 */ diff --git a/assets/script/game/map/SBox.ts b/assets/script/game/map/SBox.ts new file mode 100644 index 00000000..5dba0f53 --- /dev/null +++ b/assets/script/game/map/SBox.ts @@ -0,0 +1,52 @@ +import { instantiate, Prefab, Vec3, Node } from "cc"; +import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; +import { smc } from "../common/SingletonModuleComp"; +import { SkillBoxComp } from "./SkillBoxComp"; + +/** SBox 实体:负责技能卡效果节点创建、初始化与销毁流程 */ +@ecs.register(`SBox`) +export class SBox extends ecs.Entity { + /** 技能盒子视图和逻辑组件引用 */ + SkillBox!: SkillBoxComp; + + protected init() { + // 如果有纯逻辑数据组件可以在这里 addComponents + } + + /** 销毁实体并释放视图节点,防止残留 */ + destroy(): void { + const view = this.get(SkillBoxComp); + if (view && view.node && view.node.isValid) { + view.node.destroy(); + } + + this.remove(SkillBoxComp); + super.destroy(); + } + + /** + * 加载并初始化技能盒子 + * 1) 创建节点并挂到 SKILL 层 + * 2) 初始化表现与属性数据 + */ + load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab): Node { + let node = instantiate(prefab); + let scene = smc.map.MapView.scene; + + // 统一挂到实体显示层 SKILL 节点下 + let parent = scene.entityLayer!.node!.getChildByName("SKILL"); + if (parent) { + node.parent = parent; + } + node.setPosition(pos); + + // 获取并注册组件 + let sboxComp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp); + this.add(sboxComp); + + // 初始化业务逻辑 + sboxComp.init(uuid, card_lv); + + return node; + } +} diff --git a/assets/script/game/map/SBox.ts.meta b/assets/script/game/map/SBox.ts.meta new file mode 100644 index 00000000..cc1c0ca7 --- /dev/null +++ b/assets/script/game/map/SBox.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "10240197-8f36-4350-88cb-e3eae9567f12", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/script/game/map/SkillBoxComp.ts b/assets/script/game/map/SkillBoxComp.ts index 2f974e30..e87d5e4c 100644 --- a/assets/script/game/map/SkillBoxComp.ts +++ b/assets/script/game/map/SkillBoxComp.ts @@ -143,7 +143,11 @@ export class SkillBoxComp extends CCComp { if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) { // 次数已满且不跨波次维持 → 延迟 1 秒后销毁(保留短暂视觉反馈) this.scheduleOnce(() => { - if (this.node && this.node.isValid) this.node.destroy(); + if (this.ent) { + (this.ent as ecs.Entity).destroy(); + } else if (this.node && this.node.isValid) { + this.node.destroy(); + } }, 1.0); } } @@ -212,7 +216,11 @@ export class SkillBoxComp extends CCComp { if (this.keep_waves > 0) { this.keep_waves--; if (this.keep_waves <= 0) { - if (this.node && this.node.isValid) this.node.destroy(); + if (this.ent) { + (this.ent as ecs.Entity).destroy(); + } else if (this.node && this.node.isValid) { + this.node.destroy(); + } return; } } @@ -230,7 +238,11 @@ export class SkillBoxComp extends CCComp { // 默认逻辑:不跨波次维持 if (!this.is_instant) { if (this.current_trigger_times >= this.trigger_times) { - if (this.node && this.node.isValid) this.node.destroy(); + if (this.ent) { + (this.ent as ecs.Entity).destroy(); + } else if (this.node && this.node.isValid) { + this.node.destroy(); + } } } } @@ -238,7 +250,11 @@ export class SkillBoxComp extends CCComp { /** 任务结束:强制销毁 */ private onMissionEnd() { - this.node.destroy(); + if (this.ent) { + (this.ent as ecs.Entity).destroy(); + } else if (this.node && this.node.isValid) { + this.node.destroy(); + } } // ======================== 帧更新 ======================== @@ -264,7 +280,11 @@ export class SkillBoxComp extends CCComp { // 次数用完且不跨波次维持 → 延迟销毁 if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) { this.scheduleOnce(() => { - if (this.node && this.node.isValid) this.node.destroy(); + if (this.ent) { + (this.ent as ecs.Entity).destroy(); + } else if (this.node && this.node.isValid) { + this.node.destroy(); + } }, 0.5); } } @@ -295,6 +315,8 @@ export class SkillBoxComp extends CCComp { /** ECS 组件移除时销毁节点 */ reset() { - this.node.destroy(); + if (this.node && this.node.isValid) { + this.node.destroy(); + } } }