diff --git a/assets/script/game/skill/Skill.ts b/assets/script/game/skill/Skill.ts index 37d3b905..bc511e0a 100644 --- a/assets/script/game/skill/Skill.ts +++ b/assets/script/game/skill/Skill.ts @@ -99,11 +99,17 @@ export class Skill extends ecs.Entity { } node.parent = skillParent; + node.active = true; // 设置节点属性 let face=caster.node.scale.x < 0 ? -1 : 1 node.setScale(v3(node.scale.x*face,node.scale.y,1)) // 初始视图 - const SView = node.getComponent(SkillView); + const SView = node.getComponent(SkillView); + if (!SView) { + mLogger.error(this.debugMode, 'Skill', "[Skill] SkillView 组件缺失:", path); + if (node.isValid) node.destroy(); + return; + } if(config.EType!=EType.collision){ const collider=node.getComponent(BoxCollider2D); if(collider){ @@ -163,6 +169,7 @@ export class Skill extends ecs.Entity { sDataCom.s_uuid=s_uuid sDataCom.fac=cAttrsComp.fac sDataCom.ext_dmg=ext_dmg + SView.init(); } /** 模块资源释放 */ diff --git a/assets/script/game/skill/SkillView.ts b/assets/script/game/skill/SkillView.ts index 9416bf9a..06f5a55a 100644 --- a/assets/script/game/skill/SkillView.ts +++ b/assets/script/game/skill/SkillView.ts @@ -30,27 +30,27 @@ export class SkillView extends CCComp { sData:SDataCom=null; s_uuid:number=1001 private collider: Collider2D = null; // 缓存碰撞体引用 + private pendingDisableCollider: boolean = false; private attackFrameCount: number = 0; // 攻击帧计数器 private maxAttackFrames: number = 1; // 最大攻击帧数,可配置 // 已命中目标追踪,防止重复伤害 - start() { - this.init(); - } - init() { this.SConf = SkillSet[this.s_uuid] this.sData = this.ent.get(SDataCom) this.anim = this.node.getComponent(Animation) this.node.active = true; + this.pendingDisableCollider = false; this.collider = this.getComponent(Collider2D); if(this.collider) { this.collider.group = this.group; + this.collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); - this.collider.enabled = true; // 确保复用时开启 + this.collider.enabled = this.SConf?.EType === EType.collision; } if(this.node.getComponent(Animation)){ let anim = this.node.getComponent(Animation); mLogger.log(this.debugMode, 'SkillView', "[SkillCom]:has anim",anim) + anim.off(Animation.EventType.FINISHED, this.onAnimationFinished, this); anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this); // 对象池复用时,需要手动播放默认动画(因为 Play On Load 只在首次生效) @@ -74,6 +74,7 @@ export class SkillView extends CCComp { return; } if (oCol.group === seCol.group) return; + if (this.pendingDisableCollider) return; // 不是 HeroViewComp,直接忽略 if (!targetView) return; // 🔥 方案A:防御性检查 - 在获取model前强制检查ent是否存在 @@ -101,6 +102,7 @@ export class SkillView extends CCComp { // 开启碰撞检测 if(this.collider) { + this.pendingDisableCollider = false; this.collider.enabled = true; mLogger.log(this.debugMode, 'SkillView', `[SkillView] [${this.SConf?.name}] 第${this.attackFrameCount}次攻击帧开启碰撞检测`); } @@ -121,7 +123,7 @@ export class SkillView extends CCComp { // 对于非持续碰撞类型的技能,在造成伤害后立即关闭碰撞检测 // 这样可以避免同一帧内的重复伤害 if(this.SConf.EType !== EType.collision && this.collider) { - this.collider.enabled = false; + this.close_collider(); mLogger.log(this.debugMode, 'SkillView', `[SkillView] [${this.SConf.name}] 伤害后关闭碰撞检测`); } @@ -157,17 +159,26 @@ export class SkillView extends CCComp { } } close_collider(){ - if (this.collider) { - this.collider.enabled = false; - } + if (!this.collider || this.pendingDisableCollider) return; + this.pendingDisableCollider = true; + this.scheduleOnce(() => { + if (this.collider && this.collider.isValid) { + this.collider.enabled = false; + } + this.pendingDisableCollider = false; + }, 0); } /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ reset() { // 清理碰撞体事件监听 if (this.collider) { - this.collider.off(Contact2DType.BEGIN_CONTACT); + this.collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); this.collider.enabled = false; } + this.pendingDisableCollider = false; + if (this.anim) { + this.anim.off(Animation.EventType.FINISHED, this.onAnimationFinished, this); + } // 取消所有定时器 this.unscheduleAllCallbacks(); if (this.node && this.node.isValid) {