fix(skill): 修复技能碰撞检测逻辑和组件初始化问题
- 在Skill.ts中确保节点激活并添加SkillView组件缺失的错误处理 - 修复SkillView中碰撞体启用/禁用逻辑,避免同一帧内重复触发伤害 - 增加pendingDisableCollider标志防止异步操作中的竞争条件 - 完善组件重置逻辑,正确清理事件监听和定时器 - 修复动画事件监听可能重复绑定的问题
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
/** 模块资源释放 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user