diff --git a/assets/script/game/skill/SkillView.ts b/assets/script/game/skill/SkillView.ts index 4b6a46eb..cfad60f0 100644 --- a/assets/script/game/skill/SkillView.ts +++ b/assets/script/game/skill/SkillView.ts @@ -10,7 +10,7 @@ import { mLogger } from "../common/Logger"; const { ccclass, property } = _decorator; -/** 视图层对象 */ +/** 技能视图组件:负责碰撞窗口、碰撞回调与伤害派发 */ @ccclass('SkillView') @ecs.register('SkillView', false) export class SkillView extends CCComp { @@ -31,7 +31,7 @@ export class SkillView extends CCComp { private collider: Collider2D = null; // 缓存碰撞体引用 private pendingDisableCollider: boolean = false; private isDisposing: boolean = false; - // 已命中目标追踪,防止重复伤害 + // 生命周期保护标记,避免在销毁阶段重复处理碰撞 init() { this.SConf = SkillSet[this.s_uuid] this.sData = this.ent.get(SDataCom) @@ -75,13 +75,14 @@ export class SkillView extends CCComp { if (oCol.group === seCol.group) return; if (this.pendingDisableCollider) return; if (this.sData.hit_count >= this.sData.max_hit_count) { - this.close_collider(); + this.handle_collision_limit(); return; } this.sData.hit_count++; if (this.sData.hit_count >= this.sData.max_hit_count) { - this.close_collider(); + this.handle_collision_limit(); } + // 命中次数按碰撞事件统计:不依赖是否最终造成伤害 // 不是 HeroViewComp,直接忽略 if (!targetView) return; // 🔥 方案A:防御性检查 - 在获取model前强制检查ent是否存在 @@ -99,12 +100,13 @@ export class SkillView extends CCComp { } onAnimationFinished(){ + // animationEnd 类型:动画结束后再关闭碰撞并销毁 if(this.SConf.EType==EType.animationEnd){ this.disable_collider_now(); this.ent.destroy() } } - // //动画帧事件 atk 触发 + // 动画帧事件 atk:仅负责开启一帧碰撞窗口,不负责伤害与计数 public atk(args:any){ if(!this.SConf) return; if(this.SConf.EType==EType.collision) return @@ -117,7 +119,7 @@ export class SkillView extends CCComp { }, 0); } } - //伤害应用 + // 仅负责伤害派发,不处理命中次数与实体销毁 apply_damage(target:HeroViewComp,is_range:boolean=false){ if(target == null) return; // 安全检查:如果目标实体已不存在,直接返回 @@ -138,19 +140,6 @@ export class SkillView extends CCComp { this.sData.ext_dmg, this.sData.dmg_ratio, ); - if ( - (this.SConf.DTType != DTType.range) && - (this.SConf.EType != EType.animationEnd) && - (this.SConf.EType != EType.timeEnd) - ) { - // 修复:物理回调中不能直接销毁刚体,需延迟到下一帧 - this.close_collider(); - this.scheduleOnce(() => { - if (this.ent) { - this.ent.destroy(); - } - }, 0); - } } close_collider(){ if (!this.collider) return; @@ -165,6 +154,18 @@ export class SkillView extends CCComp { this.isDisposing = true; this.close_collider(); } + // 碰撞上限收口:先关碰撞;collision 类型再延迟销毁实体 + private handle_collision_limit() { + this.close_collider(); + if (this.SConf?.EType !== EType.collision) return; + if (this.isDisposing) return; + this.isDisposing = true; + this.scheduleOnce(() => { + if (this.ent) { + this.ent.destroy(); + } + }, 0); + } private enable_collider_safely(): boolean { if (!this.collider || !this.collider.isValid) return false; if (this.isDisposing) return false;