feat(英雄): 优化英雄移动和碰撞逻辑

fix由于 setScale 会影响物理判断,造成玩家角色多次被攻击触发回调
- 添加英雄移动方向缓存避免频繁转向
- 优化英雄碰撞器初始状态管理
- 修复英雄后退动画重复触发问题
- 调整部分英雄prefab的碰撞组和传感器设置
This commit is contained in:
2025-11-03 13:10:43 +08:00
parent 5bd2e15fb5
commit d089699c36
16 changed files with 70 additions and 35 deletions

View File

@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -961,7 +961,7 @@
"__prefab": { "__prefab": {
"__id__": 60 "__id__": 60
}, },
"enabledContactListener": true, "enabledContactListener": false,
"bullet": false, "bullet": false,
"awakeOnLoad": true, "awakeOnLoad": true,
"_group": 4, "_group": 4,
@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },
@@ -1009,7 +1009,7 @@
"_size": { "_size": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 49.3, "width": 49.3,
"height": 72.9 "height": 60.9
}, },
"_id": "" "_id": ""
}, },

View File

@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -896,8 +896,8 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 80, "width": 60,
"height": 8 "height": 80
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -988,12 +988,12 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__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,

View File

@@ -991,12 +991,12 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__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,

View File

@@ -991,7 +991,7 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },

View File

@@ -991,14 +991,14 @@
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": false, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 62 "__id__": 62
}, },
"tag": 0, "tag": 0,
"_group": 2, "_group": 2,
"_density": 1, "_density": 1,
"_sensor": false, "_sensor": true,
"_friction": 0.2, "_friction": 0.2,
"_restitution": 0, "_restitution": 0,
"_offset": { "_offset": {

View File

@@ -513,7 +513,7 @@
"tag": 0, "tag": 0,
"_group": 1, "_group": 1,
"_density": 1, "_density": 1,
"_sensor": false, "_sensor": true,
"_friction": 0.2, "_friction": 0.2,
"_restitution": 0, "_restitution": 0,
"_offset": { "_offset": {

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "e44e387b-e119-4ea3-8c61-90be55888ce5",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -1,4 +1,4 @@
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas} from "cc"; import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D} from "cc";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { smc } from "../common/SingletonModuleComp"; import { smc } from "../common/SingletonModuleComp";
@@ -47,6 +47,8 @@ export class Hero extends ecs.Entity {
var node = instantiate(prefab); var node = instantiate(prefab);
var scene = smc.map.MapView.scene; var scene = smc.map.MapView.scene;
node.parent = scene.entityLayer!.node! node.parent = scene.entityLayer!.node!
const collider = node.getComponent(BoxCollider2D);
if (collider) collider.enabled = false; // 先禁用
node.setPosition(pos) node.setPosition(pos)
// console.log("hero load",pos) // console.log("hero load",pos)
var hv = node.getComponent(HeroViewComp)!; var hv = node.getComponent(HeroViewComp)!;

View File

@@ -15,11 +15,14 @@ export class HeroMoveComp extends ecs.Comp {
targetX: number = 0; targetX: number = 0;
/** 是否处于移动状态 */ /** 是否处于移动状态 */
moving: boolean = true; moving: boolean = true;
/** 当前朝向缓存避免频繁setScale */
currentFacing: number = 1;
reset() { reset() {
this.direction = 1; this.direction = 1;
this.targetX = 0; this.targetX = 0;
this.moving = true; this.moving = true;
this.currentFacing = 1;
} }
} }
@@ -73,12 +76,10 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
// 根据敌人位置调整移动方向和朝向 // 根据敌人位置调整移动方向和朝向
if (enemyX > currentX) { if (enemyX > currentX) {
move.direction = 1; // 向右移动 move.direction = 1; // 向右移动
view.node.setScale(1, 1, 1); // 面向右侧 this.setFacing(view, move, 1); // 🔥 使用优化的转向方法
view.node.getChildByName("top").setScale(1, 1, 1); // 面向右侧
} else { } else {
move.direction = -1; // 向左移动 move.direction = -1; // 向左移动
view.node.setScale(-1, 1, 1); // 面向左侧 this.setFacing(view, move, -1); // 🔥 使用优化的转向方法
view.node.getChildByName("top").setScale(-1, 1, 1); // 面向左侧
} }
// 继续向敌人方向移动 // 继续向敌人方向移动
@@ -112,14 +113,8 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
const delta = (model.Attrs[Attrs.SPEED]/3) * this.dt * direction; const delta = (model.Attrs[Attrs.SPEED]/3) * this.dt * direction;
const newX = view.node.position.x + delta; const newX = view.node.position.x + delta;
// 设置朝向 // 🔥 使用优化的转向方法
if (direction === 1) { this.setFacing(view, move, direction);
view.node.setScale(1, 1, 1); // 面向右侧
view.node.getChildByName("top").setScale(1, 1, 1); // 面向右侧
} else {
view.node.setScale(-1, 1, 1); // 面向左侧
view.node.getChildByName("top").setScale(-1, 1, 1); // 面向左侧
}
// 确保不会超过目标位置 // 确保不会超过目标位置
if (direction === 1 && newX > finalTargetX) { if (direction === 1 && newX > finalTargetX) {
@@ -134,8 +129,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
view.status_change("idle"); view.status_change("idle");
// 到达目标位置后,面向右侧(敌人方向) // 到达目标位置后,面向右侧(敌人方向)
move.direction = 1; move.direction = 1;
view.node.setScale(1, 1, 1); // 面向右侧 this.setFacing(view, move, 1); // 🔥 使用优化的转向方法
view.node.getChildByName("top").setScale(1, 1, 1); // 面向右侧
} }
} else { } else {
view.status_change("idle"); view.status_change("idle");
@@ -143,6 +137,24 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
} }
} }
/**
* 🔥 优化的转向方法只在真正需要改变朝向时才调用setScale
* 避免频繁的setScale调用导致碰撞器重新计算
*/
private setFacing(view: HeroViewComp, move: HeroMoveComp, newFacing: number) {
// 只有当朝向真正改变时才更新
if (move.currentFacing !== newFacing) {
move.currentFacing = newFacing;
view.node.setScale(newFacing, 1, 1);
// 安全获取top节点
const topNode = view.node.getChildByName("top");
if (topNode) {
topNode.setScale(newFacing, 1, 1);
}
}
}
/** 检查是否存在敌人 */ /** 检查是否存在敌人 */
private checkEnemiesExist(entity: ecs.Entity): boolean { private checkEnemiesExist(entity: ecs.Entity): boolean {
const team = entity.get(HeroAttrsComp).fac; const team = entity.get(HeroAttrsComp).fac;

View File

@@ -311,12 +311,24 @@ export class HeroViewComp extends CCComp {
this.back() this.back()
this.showDamage(damage, isCrit, SConf.DAnm); // 暴击状态由战斗系统内部处理, DAnm和EAnm共用设定数组 this.showDamage(damage, isCrit, SConf.DAnm); // 暴击状态由战斗系统内部处理, DAnm和EAnm共用设定数组
} }
private isBackingUp: boolean = false; // 🔥 添加后退状态标记
//后退 //后退
back(){ back(){
// 🔥 防止重复调用后退动画
if (this.isBackingUp) return;
if(this.model.fac==FacSet.MON) { if(this.model.fac==FacSet.MON) {
this.isBackingUp = true; // 🔥 设置后退状态
let tx=this.node.position.x+30 let tx=this.node.position.x+30
if(tx > 320) tx=320 if(tx > 320) tx=320
tween(this.node).to(0.1, { position:v3(tx,this.node.position.y,0)}).start() tween(this.node)
.to(0.1, { position:v3(tx,this.node.position.y,0)})
.call(() => {
this.isBackingUp = false; // 🔥 动画完成后重置状态
})
.start()
} }
//英雄不再后退 //英雄不再后退
// if(this.model.fac==FacSet.HERO) { // if(this.model.fac==FacSet.HERO) {