refactor(skill): 重构技能盒子管理为ECS实体架构
新增SBox ECS实体,统一管理技能盒子的创建、挂载与销毁 重构MissSkillsComp,改用SBox实体替代直接实例化技能节点 更新SkillBoxComp,新增实体引用以通过ECS生命周期销毁节点 临时调整SCastSystem的索敌范围为全屏级,方便测试
This commit is contained in:
@@ -113,6 +113,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
|||||||
mockAttrs.puncture_chance = 0;
|
mockAttrs.puncture_chance = 0;
|
||||||
mockAttrs.fac = FacSet.HERO;
|
mockAttrs.fac = FacSet.HERO;
|
||||||
mockAttrs.type = HType.Long; // 假定为远程,拥有较长索敌范围
|
mockAttrs.type = HType.Long; // 假定为远程,拥有较长索敌范围
|
||||||
|
mockAttrs.dis = 2000; // 给予全屏以上的索敌范围
|
||||||
|
|
||||||
let targetPos: Vec3 | null = null;
|
let targetPos: Vec3 | null = null;
|
||||||
if (!isFriendly) {
|
if (!isFriendly) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { _decorator, Node, Prefab, instantiate, Vec3 } from "cc";
|
|||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
import { SkillBoxComp } from "./SkillBoxComp";
|
import { SkillBoxComp } from "./SkillBoxComp";
|
||||||
|
import { SBox } from "./SBox";
|
||||||
import { oops } from "db://oops-framework/core/Oops";
|
import { oops } from "db://oops-framework/core/Oops";
|
||||||
import { GameEvent } from "../common/config/GameEvent";
|
import { GameEvent } from "../common/config/GameEvent";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
@@ -164,9 +165,6 @@ export class MissSkillsComp extends CCComp {
|
|||||||
* @param card_lv 技能卡等级
|
* @param card_lv 技能卡等级
|
||||||
*/
|
*/
|
||||||
addSkill(uuid: number, card_lv: number) {
|
addSkill(uuid: number, card_lv: number) {
|
||||||
// 技能节点的父容器
|
|
||||||
var parent = smc.map.MapView.scene.entityLayer!.node!.getChildByName("SKILL")!;
|
|
||||||
|
|
||||||
if (!this.skill_box) {
|
if (!this.skill_box) {
|
||||||
mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set");
|
mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set");
|
||||||
return;
|
return;
|
||||||
@@ -179,17 +177,13 @@ export class MissSkillsComp extends CCComp {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 实例化并放入槽位
|
// 使用 ECS 实体创建技能节点
|
||||||
const node = instantiate(this.skill_box);
|
let sbox = ecs.getEntity<SBox>(SBox);
|
||||||
node.parent = parent;
|
let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0);
|
||||||
node.setPosition(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].used = true;
|
||||||
this.slots[emptyIndex].node = node;
|
this.slots[emptyIndex].node = node;
|
||||||
|
|
||||||
// 初始化技能效果组件
|
|
||||||
const comp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp);
|
|
||||||
comp.init(uuid, card_lv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ECS 组件移除时销毁节点 */
|
/** ECS 组件移除时销毁节点 */
|
||||||
|
|||||||
52
assets/script/game/map/SBox.ts
Normal file
52
assets/script/game/map/SBox.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
assets/script/game/map/SBox.ts.meta
Normal file
9
assets/script/game/map/SBox.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "10240197-8f36-4350-88cb-e3eae9567f12",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -143,7 +143,11 @@ export class SkillBoxComp extends CCComp {
|
|||||||
if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) {
|
if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) {
|
||||||
// 次数已满且不跨波次维持 → 延迟 1 秒后销毁(保留短暂视觉反馈)
|
// 次数已满且不跨波次维持 → 延迟 1 秒后销毁(保留短暂视觉反馈)
|
||||||
this.scheduleOnce(() => {
|
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);
|
}, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +216,11 @@ export class SkillBoxComp extends CCComp {
|
|||||||
if (this.keep_waves > 0) {
|
if (this.keep_waves > 0) {
|
||||||
this.keep_waves--;
|
this.keep_waves--;
|
||||||
if (this.keep_waves <= 0) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +238,11 @@ export class SkillBoxComp extends CCComp {
|
|||||||
// 默认逻辑:不跨波次维持
|
// 默认逻辑:不跨波次维持
|
||||||
if (!this.is_instant) {
|
if (!this.is_instant) {
|
||||||
if (this.current_trigger_times >= this.trigger_times) {
|
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() {
|
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) {
|
if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) {
|
||||||
this.scheduleOnce(() => {
|
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);
|
}, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,6 +315,8 @@ export class SkillBoxComp extends CCComp {
|
|||||||
|
|
||||||
/** ECS 组件移除时销毁节点 */
|
/** ECS 组件移除时销毁节点 */
|
||||||
reset() {
|
reset() {
|
||||||
this.node.destroy();
|
if (this.node && this.node.isValid) {
|
||||||
|
this.node.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user