refactor(skill): 优化技能碰撞检测逻辑并移除重复命中检查
- 移除hitTargets集合及相关重复命中检查逻辑 - 改进碰撞检测日志输出,增加安全性检查 - 清理注释掉的旧攻击逻辑代码 - 在reset方法中添加碰撞器事件解绑
This commit is contained in:
@@ -996,7 +996,7 @@
|
|||||||
"__id__": 62
|
"__id__": 62
|
||||||
},
|
},
|
||||||
"tag": 0,
|
"tag": 0,
|
||||||
"_group": 4,
|
"_group": 2,
|
||||||
"_density": 1,
|
"_density": 1,
|
||||||
"_sensor": true,
|
"_sensor": true,
|
||||||
"_friction": 0.2,
|
"_friction": 0.2,
|
||||||
|
|||||||
@@ -996,9 +996,9 @@
|
|||||||
"__id__": 62
|
"__id__": 62
|
||||||
},
|
},
|
||||||
"tag": 0,
|
"tag": 0,
|
||||||
"_group": 4,
|
"_group": 2,
|
||||||
"_density": 1,
|
"_density": 1,
|
||||||
"_sensor": true,
|
"_sensor": false,
|
||||||
"_friction": 0.2,
|
"_friction": 0.2,
|
||||||
"_restitution": 0,
|
"_restitution": 0,
|
||||||
"_offset": {
|
"_offset": {
|
||||||
|
|||||||
@@ -301,7 +301,7 @@
|
|||||||
"bullet": false,
|
"bullet": false,
|
||||||
"awakeOnLoad": true,
|
"awakeOnLoad": true,
|
||||||
"_group": 1,
|
"_group": 1,
|
||||||
"_type": 2,
|
"_type": 1,
|
||||||
"_allowSleep": false,
|
"_allowSleep": false,
|
||||||
"_gravityScale": 1,
|
"_gravityScale": 1,
|
||||||
"_linearDamping": 0,
|
"_linearDamping": 0,
|
||||||
|
|||||||
@@ -513,7 +513,7 @@
|
|||||||
"tag": 0,
|
"tag": 0,
|
||||||
"_group": 1,
|
"_group": 1,
|
||||||
"_density": 1,
|
"_density": 1,
|
||||||
"_sensor": true,
|
"_sensor": false,
|
||||||
"_friction": 0.2,
|
"_friction": 0.2,
|
||||||
"_restitution": 0,
|
"_restitution": 0,
|
||||||
"_offset": {
|
"_offset": {
|
||||||
|
|||||||
@@ -304,8 +304,8 @@
|
|||||||
"bullet": false,
|
"bullet": false,
|
||||||
"awakeOnLoad": true,
|
"awakeOnLoad": true,
|
||||||
"_group": 1,
|
"_group": 1,
|
||||||
"_type": 2,
|
"_type": 1,
|
||||||
"_allowSleep": true,
|
"_allowSleep": false,
|
||||||
"_gravityScale": 1,
|
"_gravityScale": 1,
|
||||||
"_linearDamping": 0,
|
"_linearDamping": 0,
|
||||||
"_angularDamping": 0,
|
"_angularDamping": 0,
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ export class SkillView extends CCComp {
|
|||||||
sData:SDataCom=null;
|
sData:SDataCom=null;
|
||||||
s_uuid:number=1001
|
s_uuid:number=1001
|
||||||
// 已命中目标追踪,防止重复伤害
|
// 已命中目标追踪,防止重复伤害
|
||||||
private hitTargets: Set<string> = new Set();
|
|
||||||
start() {
|
start() {
|
||||||
this.SConf = SkillSet[this.s_uuid]
|
this.SConf = SkillSet[this.s_uuid]
|
||||||
this.sData=this.ent.get(SDataCom)
|
this.sData=this.ent.get(SDataCom)
|
||||||
@@ -49,24 +48,28 @@ export class SkillView extends CCComp {
|
|||||||
|
|
||||||
}
|
}
|
||||||
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
|
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
|
||||||
const targetId = oCol.uuid;
|
// 安全获取双方信息用于日志
|
||||||
if(this.hitTargets.has(targetId)) return; // 已经命中过,跳过
|
const casterName = this.sData.caster?.ent?.get(HeroAttrsComp)?.hero_name ?? '未知施法者';
|
||||||
// 记录命中目标
|
const casterEid = this.sData.caster?.ent?.eid ?? '未知EID';
|
||||||
|
const targetView = oCol.getComponent(HeroViewComp);
|
||||||
// if (!this.SConf) return;
|
const targetName = targetView?.ent?.get(HeroAttrsComp)?.hero_name ?? '非英雄对象';
|
||||||
// if(this.SConf.EType!=EType.collision) return
|
const targetEid = targetView?.ent?.eid ?? '未知EID';
|
||||||
if(oCol.group == seCol.group) return
|
console.log(`[skillView] 碰撞1 [${this.sData.caster.box_group}][${casterName}][${casterEid}]的[${seCol.group}]:[${this.SConf.name}][${this.ent.eid}]碰撞了 [${oCol.group}]:[ ${targetName}][${targetEid}]`);
|
||||||
let target = oCol.getComponent(HeroViewComp)
|
// 基本空值与同组过滤
|
||||||
if(target == null) return;
|
if (!this.sData || !this.SConf) {
|
||||||
let model=target.ent.get(HeroAttrsComp)
|
console.warn('[SkillView] onBeginContact 缺少 sData 或 SConf,忽略此次碰撞');
|
||||||
console.log(`[skillView] 碰撞3`,oCol.group,seCol.group,model);
|
return;
|
||||||
if(model == null) return
|
}
|
||||||
if(model.is_dead) return
|
if (oCol.group === seCol.group) return;
|
||||||
|
// 不是 HeroViewComp,直接忽略
|
||||||
|
if (!targetView) return;
|
||||||
|
let model = targetView.ent.get(HeroAttrsComp);
|
||||||
|
// console.log(`[skillView] 碰撞3`, oCol.group, seCol.group, model);
|
||||||
|
if (!model) return;
|
||||||
|
if (model.is_dead) return;
|
||||||
if (this.sData.fac == model.fac) return;
|
if (this.sData.fac == model.fac) return;
|
||||||
// 检查是否已经命中过这个目标
|
// 检查是否已经命中过这个目标(日志安全输出)
|
||||||
console.log(`[skillView] 碰撞5[${this.sData.caster.box_group}][${this.sData.caster.ent.get(HeroAttrsComp).hero_name}][${this.sData.caster.ent.eid}]的[${this.group}] [${this.SConf.name}]碰撞了 [${oCol.group}][ ${oCol.getComponent(HeroViewComp).ent.get(HeroAttrsComp).hero_name}][${oCol.getComponent(HeroViewComp).ent.eid}]`);
|
this.apply_damage(targetView)
|
||||||
this.hitTargets.add(targetId);
|
|
||||||
this.apply_damage(target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onAnimationFinished(){
|
onAnimationFinished(){
|
||||||
@@ -74,70 +77,59 @@ export class SkillView extends CCComp {
|
|||||||
this.ent.destroy()
|
this.ent.destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//动画帧事件 atk 触发
|
// //动画帧事件 atk 触发
|
||||||
public atk(args:any){
|
// public atk(args:any){
|
||||||
let dis=this.node.getComponent(UITransform).width/2
|
// let dis=this.node.getComponent(UITransform).width/2
|
||||||
let enemys:any=[]
|
// let enemys:any=[]
|
||||||
if( this.sData.fac==FacSet.HERO){
|
// if( this.sData.fac==FacSet.HERO){
|
||||||
enemys=ecs.query(ecs.allOf(MonMoveComp))
|
// enemys=ecs.query(ecs.allOf(MonMoveComp))
|
||||||
}else{
|
// }else{
|
||||||
enemys=ecs.query(ecs.allOf(HeroMoveComp))
|
// enemys=ecs.query(ecs.allOf(HeroMoveComp))
|
||||||
}
|
// }
|
||||||
let IRTargets: HeroViewComp[] = []
|
// let IRTargets: HeroViewComp[] = []
|
||||||
// 收集范围内所有敌方目标
|
// // 收集范围内所有敌方目标
|
||||||
enemys.some(e => {
|
// enemys.some(e => {
|
||||||
const view = e.get(HeroViewComp);
|
// const view = e.get(HeroViewComp);
|
||||||
const model=e.get(HeroAttrsComp)
|
// const model=e.get(HeroAttrsComp)
|
||||||
const distance = Math.abs(this.node.position.x - view.node.position.x);
|
// const distance = Math.abs(this.node.position.x - view.node.position.x);
|
||||||
if(distance <= dis&&!model.is_dead) {
|
// if(distance <= dis&&!model.is_dead) {
|
||||||
IRTargets.push(view);
|
// IRTargets.push(view);
|
||||||
}
|
// }
|
||||||
|
|
||||||
});
|
// });
|
||||||
// 根据配置的hit_num决定攻击模式
|
// // 根据配置的hit_num决定攻击模式
|
||||||
const hitNum = SkillSet[this.s_uuid].hit_num || 0;
|
// const hitNum = SkillSet[this.s_uuid].hit_num || 0;
|
||||||
if(hitNum > 0) {
|
// if(hitNum > 0) {
|
||||||
// 限制目标数量:按距离排序,选择最近的N个目标
|
// // 限制目标数量:按距离排序,选择最近的N个目标
|
||||||
if(IRTargets.length > 0) {
|
// if(IRTargets.length > 0) {
|
||||||
// 按距离排序(从近到远)
|
// // 按距离排序(从近到远)
|
||||||
IRTargets.sort((a, b) => {
|
// IRTargets.sort((a, b) => {
|
||||||
const distanceA = Math.abs(this.node.position.x - a.node.position.x);
|
// const distanceA = Math.abs(this.node.position.x - a.node.position.x);
|
||||||
const distanceB = Math.abs(this.node.position.x - b.node.position.x);
|
// const distanceB = Math.abs(this.node.position.x - b.node.position.x);
|
||||||
return distanceA - distanceB;
|
// return distanceA - distanceB;
|
||||||
});
|
// });
|
||||||
// 限制目标数量
|
// // 限制目标数量
|
||||||
const maxTargets = Math.min(hitNum, IRTargets.length);
|
// const maxTargets = Math.min(hitNum, IRTargets.length);
|
||||||
const sTargets = IRTargets.slice(0, maxTargets);
|
// const sTargets = IRTargets.slice(0, maxTargets);
|
||||||
sTargets.forEach(target => {
|
// sTargets.forEach(target => {
|
||||||
this.apply_damage(target, false);
|
// this.apply_damage(target, false);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
// 范围伤害:对所有范围内目标造成伤害
|
// // 范围伤害:对所有范围内目标造成伤害
|
||||||
if(IRTargets.length > 0) {
|
// if(IRTargets.length > 0) {
|
||||||
IRTargets.forEach(target => {
|
// IRTargets.forEach(target => {
|
||||||
this.apply_damage(target, true);
|
// this.apply_damage(target, true);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
//伤害应用
|
//伤害应用
|
||||||
apply_damage(target:HeroViewComp,is_range:boolean=false){
|
apply_damage(target:HeroViewComp,is_range:boolean=false){
|
||||||
if(target == null) return;
|
if(target == null) return;
|
||||||
if (!this.SConf) return;
|
if (!this.SConf) return;
|
||||||
|
|
||||||
// 检查是否已经命中过这个目标(除非是范围伤害)
|
// console.log(`[skillView] 伤害 [${this.group}][${this.sData.caster.ent.get(HeroAttrsComp).hero_name}][${this.sData.caster.ent.eid}]的 [${this.SConf.name}]对 [${target.box_group}][ ${target.ent.get(HeroAttrsComp).hero_name}][${target.ent.eid}]`);
|
||||||
const targetId = target.node.uuid;
|
|
||||||
if(!is_range && this.hitTargets.has(targetId)) {
|
|
||||||
return; // 已经命中过,跳过
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录命中目标(除非是范围伤害)
|
|
||||||
if(!is_range) {
|
|
||||||
this.hitTargets.add(targetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[skillView] 伤害 [${this.group}][${this.sData.caster.ent.get(HeroAttrsComp).hero_name}][${this.sData.caster.ent.eid}]的 [${this.SConf.name}]对 [${target.box_group}][ ${target.ent.get(HeroAttrsComp).hero_name}][${target.ent.eid}]`);
|
|
||||||
// if(this.sData.hit_count > this.SConf.hit_num) return 不能超出 最大伤害数量
|
// if(this.sData.hit_count > this.SConf.hit_num) return 不能超出 最大伤害数量
|
||||||
// 使用伤害队列系统处理伤害
|
// 使用伤害队列系统处理伤害
|
||||||
DamageQueueHelper.addDamageToEntity(
|
DamageQueueHelper.addDamageToEntity(
|
||||||
@@ -149,10 +141,21 @@ export class SkillView extends CCComp {
|
|||||||
// 更新技能命中次数
|
// 更新技能命中次数
|
||||||
this.sData.hit_count++
|
this.sData.hit_count++
|
||||||
// 检查技能是否应该销毁
|
// 检查技能是否应该销毁
|
||||||
if( this.sData.hit_count>=(this.SConf.hit+ this.sData.Attrs[Attrs.PUNCTURE])&&(this.SConf.DTType!=DTType.range)&&(this.SConf.EType!=EType.animationEnd)&&(this.SConf.EType!=EType.timeEnd)) this.ent.destroy// 技能命中次数
|
if (
|
||||||
|
this.sData.hit_count >= (this.SConf.hit + this.sData.Attrs[Attrs.PUNCTURE]) &&
|
||||||
|
(this.SConf.DTType != DTType.range) &&
|
||||||
|
(this.SConf.EType != EType.animationEnd) &&
|
||||||
|
(this.SConf.EType != EType.timeEnd)
|
||||||
|
) {
|
||||||
|
this.ent.destroy(); // 技能命中次数达到上限后销毁
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||||
reset() {
|
reset() {
|
||||||
|
const collider = this.getComponent(Collider2D);
|
||||||
|
if (collider) {
|
||||||
|
collider.off(Contact2DType.BEGIN_CONTACT);
|
||||||
|
}
|
||||||
this.node.destroy();
|
this.node.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user