refactor(skill): 重构技能系统以支持对象池复用
将技能节点管理改为使用对象池模式,提高性能 添加技能节点复用时的初始化逻辑 统一技能组件获取和重置方式 更新英雄配置中的默认技能
This commit is contained in:
@@ -166,11 +166,11 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 1. 基础近战型
|
||||
5201:{uuid:5201,name:"兽人战士",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.warrior,lv:1,hp:40,mp:100,def:0,ap:5,dis:60,speed:180,skills:[6201],
|
||||
type:HType.warrior,lv:1,hp:40,mp:100,def:0,ap:5,dis:60,speed:180,skills:[6005],
|
||||
buff:[],tal:[],info:"标准炮灰:确保英雄能完成3次普攻积累天赋计数"},
|
||||
// 2. 快速突击型
|
||||
5301:{uuid:5301,name:"兽人斥候",path:"mo1", fac:FacSet.MON, kind:1,as:1.2,
|
||||
type:HType.assassin,lv:1,hp:30,mp:100,def:0,ap:12,dis:50,speed:400,skills:[6201],
|
||||
type:HType.assassin,lv:1,hp:30,mp:100,def:0,ap:12,dis:50,speed:400,skills:[6005],
|
||||
buff:[],tal:[],info:"快速突击:极高移速贴脸,检测护盾(7102)刷新率"},
|
||||
// 3. 重型坦克型
|
||||
5401:{uuid:5401,name:"兽人卫士",path:"mo1", fac:FacSet.MON, kind:1,as:5.0,
|
||||
@@ -184,7 +184,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 5. 特殊机制型
|
||||
5601:{uuid:5601,name:"兽人自爆兵",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
type:HType.assassin,lv:1,hp:60,mp:100,def:0,ap:250,dis:50,speed:220,skills:[6201],
|
||||
type:HType.assassin,lv:1,hp:60,mp:100,def:0,ap:250,dis:50,speed:220,skills:[6005],
|
||||
buff:[],tal:[],info:"特殊机制:极端伤害,漏怪即秒杀,检测减伤(7103)"},
|
||||
// 召唤师:持续召唤小怪(后续可在技能系统中实现 SType.zhaohuan)
|
||||
5602:{uuid:5602,name:"兽人召唤师",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BoxCollider2D, instantiate, Node, Prefab, v3, Vec3 } from "cc";
|
||||
import { BoxCollider2D, instantiate, Node, Prefab, v3, Vec3, NodePool } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { EType, SkillSet } from "../common/config/SkillSet";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
@@ -13,10 +13,34 @@ import { smc } from "../common/SingletonModuleComp";
|
||||
/** Skill 模块 */
|
||||
@ecs.register(`Skill`)
|
||||
export class Skill extends ecs.Entity {
|
||||
/** 多键对象池:Map<prefabPath, NodePool> */
|
||||
static pools: Map<string, NodePool> = new Map();
|
||||
|
||||
static getFromPool(path: string): Node | null {
|
||||
if (this.pools.has(path)) {
|
||||
const pool = this.pools.get(path)!;
|
||||
if (pool.size() > 0) {
|
||||
return pool.get();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static putToPool(path: string, node: Node) {
|
||||
if (!this.pools.has(path)) {
|
||||
this.pools.set(path, new NodePool());
|
||||
}
|
||||
this.pools.get(path)!.put(node);
|
||||
}
|
||||
|
||||
/** ---------- 数据层 ---------- */
|
||||
SDataCom!: SDataCom;
|
||||
SMoveCom!: SMoveDataComp
|
||||
|
||||
/** 当前技能的预制体路径(用于对象池回收) */
|
||||
private prefabPath: string = "";
|
||||
private skillNode: Node | null = null; // 持有节点引用以便销毁时回收
|
||||
|
||||
/** ---------- 业务层 ---------- */
|
||||
// SkillBll!: SkillBllComp;
|
||||
|
||||
@@ -73,8 +97,11 @@ export class Skill extends ecs.Entity {
|
||||
node.setPosition(startPos);
|
||||
|
||||
// 初始化移动组件 - 从SkillView获取移动参数
|
||||
|
||||
const sMoveCom = this.get(SMoveDataComp);
|
||||
let sMoveCom = this.get(SMoveDataComp);
|
||||
if (!sMoveCom) {
|
||||
sMoveCom = this.add(SMoveDataComp);
|
||||
}
|
||||
sMoveCom.reset(); // 复用组件时重置状态
|
||||
sMoveCom.startPos.set(startPos);
|
||||
sMoveCom.targetPos.set(targetPos);
|
||||
sMoveCom.s_uuid = s_uuid;
|
||||
@@ -87,7 +114,11 @@ export class Skill extends ecs.Entity {
|
||||
|
||||
let cAttrsComp=caster.ent.get(HeroAttrsComp)
|
||||
// 初始化数据组件
|
||||
const sDataCom = this.get(SDataCom);
|
||||
let sDataCom = this.get(SDataCom);
|
||||
if (!sDataCom) {
|
||||
sDataCom = this.add(SDataCom);
|
||||
}
|
||||
sDataCom.reset();
|
||||
sDataCom.group=caster.box_group
|
||||
sDataCom.caster=caster
|
||||
sDataCom.Attrs={...cAttrsComp.Attrs}
|
||||
@@ -101,7 +132,16 @@ export class Skill extends ecs.Entity {
|
||||
// 注: 自定义释放逻辑,视图层实现 ecs.IComp 接口的 ecs 组件需要手动释放
|
||||
this.remove(SDataCom);
|
||||
this.remove(SMoveDataComp)
|
||||
|
||||
// 移除组件会触发 reset,但我们在 reset 中移除了 destroy
|
||||
this.remove(SkillView)
|
||||
|
||||
// 回收节点到对象池
|
||||
if (this.skillNode && this.skillNode.isValid && this.prefabPath) {
|
||||
Skill.putToPool(this.prefabPath, this.skillNode);
|
||||
this.skillNode = null;
|
||||
}
|
||||
|
||||
super.destroy();
|
||||
|
||||
}
|
||||
|
||||
@@ -30,21 +30,31 @@ export class SkillView extends CCComp {
|
||||
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.sData = this.ent.get(SDataCom)
|
||||
this.anim = this.node.getComponent(Animation)
|
||||
this.node.active = true;
|
||||
this.collider = this.getComponent(Collider2D);
|
||||
if(this.collider) {
|
||||
this.collider.group = this.group;
|
||||
this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||
this.collider.enabled = true; // 确保复用时开启
|
||||
}
|
||||
if(this.node.getComponent(Animation)){
|
||||
let anim = this.node.getComponent(Animation);
|
||||
//console.log("[SkillCom]:has anim",anim)
|
||||
anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
|
||||
|
||||
// 对象池复用时,需要手动播放默认动画(因为 Play On Load 只在首次生效)
|
||||
if (anim.defaultClip) {
|
||||
anim.play(anim.defaultClip.name);
|
||||
}
|
||||
}
|
||||
|
||||
this.attackFrameCount = 0; // 重置攻击帧计数
|
||||
}
|
||||
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
|
||||
// 安全获取双方信息用于日志
|
||||
|
||||
Reference in New Issue
Block a user