refactor(skill): 重构技能配置加载逻辑,将参数下沉至prefab配置
1. 新增SkillView组件属性runType/endType/speed/time,替换原配置表字段 2. 批量同步所有技能prefab的配置参数 3. 优化技能运行逻辑,优先使用prefab配置,配置表仅作兜底 4. 新增同步脚本用于批量迁移技能配置
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// ========== 从 HeroAttrs.ts 导入属性相关定义 ==========
|
||||
// ========== 从 HeroAttrs.ts 导入属性相关定义 ==========
|
||||
import { Attrs } from "./HeroAttrs";
|
||||
|
||||
export enum HSSet {
|
||||
@@ -134,6 +134,7 @@ export interface SkillConfig {
|
||||
gold?: number, // 获取金币技能的金币值
|
||||
hit_count: number, // 可命中次数
|
||||
hitcd: number, // 持续伤害的伤害间隔(秒)
|
||||
/** @deprecated 已下沉到 SkillView @property(prefab 配置),此处仅作兜底 */
|
||||
speed: number, // 移动速度
|
||||
with: number, // 宽度(暂时无用)
|
||||
ready: number, // 前摇时间
|
||||
@@ -142,11 +143,14 @@ export interface SkillConfig {
|
||||
EAnm: number, // 结束动画ID
|
||||
DAnm: string, // 命中后动画ID
|
||||
IType: IType, // 技能类型(近战/远程/辅助)
|
||||
/** @deprecated 已下沉到 SkillView @property(prefab 配置),此处仅作兜底 */
|
||||
RType: RType, // 技能运行类型(直线/贝塞尔/固定起点/固定终点)
|
||||
/** @deprecated 已下沉到 SkillView @property(prefab 配置),此处仅作兜底 */
|
||||
EType: EType, // 结束条件(动画结束/时间结束/距离结束/碰撞/次数结束)
|
||||
bezier_start_y?: number, // 贝塞尔起始抬升高度
|
||||
bezier_mid_y?: number, // 贝塞尔中间高度增量
|
||||
bezier_arc?: number, // 贝塞尔弧度系数
|
||||
/** @deprecated 已下沉到 SkillView @property(prefab 配置),此处仅作兜底 */
|
||||
time?: number, // timeEnd 持续时间(秒)
|
||||
kind?: SkillKind, // 主效果类型
|
||||
crt?: number, // 额外暴击率
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { v3, Vec3 ,Node} from "cc";
|
||||
import { v3, Vec3, Node } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { EType, RType, SkillSet } from "../common/config/SkillSet";
|
||||
import { SMoveDataComp } from "./SMoveComp";
|
||||
@@ -26,46 +26,46 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(SMoveDataComp, SkillView);
|
||||
}
|
||||
|
||||
|
||||
entityEnter(entity: ecs.Entity): void {
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
const skillView = entity.get(SkillView);
|
||||
|
||||
|
||||
if (!moveComp || !skillView || !skillView.node) return;
|
||||
|
||||
|
||||
// 获取技能配置
|
||||
const skillConfig = SkillSet[moveComp.s_uuid];
|
||||
if (!skillConfig) {
|
||||
mLogger.warn(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能配置不存在: ${moveComp.s_uuid}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据配置设置移动速度与加速度
|
||||
if (skillConfig.speed > 0) {
|
||||
|
||||
// 移动参数由 prefab 的 SkillView @property 决定(speed<=0 时 Skill.load 已回退配置表值)
|
||||
if (moveComp.speed <= 0) {
|
||||
moveComp.speed = skillConfig.speed;
|
||||
}
|
||||
if (skillConfig.is_accel) {
|
||||
moveComp.isAccelerate = true;
|
||||
}
|
||||
|
||||
|
||||
// 根据runType设置初始位置
|
||||
this.initializePosition(moveComp, skillView);
|
||||
|
||||
|
||||
// 开始移动(除了固定位置类型)
|
||||
if (moveComp.runType !== RType.fixed && moveComp.runType !== RType.fixedEnd) {
|
||||
moveComp.startMove();
|
||||
}
|
||||
|
||||
|
||||
mLogger.log(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能 ${skillConfig.name} 开始移动,类型: ${moveComp.runType}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据runType初始化技能位置
|
||||
*/
|
||||
private initializePosition(moveComp: SMoveDataComp, skillView: SkillView): void {
|
||||
const node = skillView.node;
|
||||
|
||||
switch(moveComp.runType) {
|
||||
|
||||
switch (moveComp.runType) {
|
||||
case RType.linear:
|
||||
// linear类型:根据atk_x和atk_y调整起始位置
|
||||
const adjustedStartPos = v3(
|
||||
@@ -73,35 +73,35 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
moveComp.startPos.y + moveComp.atk_y,
|
||||
moveComp.startPos.z
|
||||
);
|
||||
|
||||
|
||||
const originTargetPos = v3(
|
||||
moveComp.targetPos.x,
|
||||
moveComp.targetPos.y,
|
||||
moveComp.targetPos.z
|
||||
);
|
||||
|
||||
|
||||
const direction = new Vec3();
|
||||
Vec3.subtract(direction, originTargetPos, adjustedStartPos);
|
||||
|
||||
|
||||
// 延长终止点,统一消亡点的x坐标为 +-500
|
||||
const targetX = moveComp.scale > 0 ? 500 : -500;
|
||||
let targetY = originTargetPos.y;
|
||||
|
||||
|
||||
if (Math.abs(direction.x) > 0.01) {
|
||||
const slope = direction.y / direction.x;
|
||||
targetY = adjustedStartPos.y + slope * (targetX - adjustedStartPos.x);
|
||||
}
|
||||
|
||||
|
||||
const adjustedTargetPos = v3(
|
||||
targetX,
|
||||
targetY,
|
||||
originTargetPos.z
|
||||
);
|
||||
|
||||
|
||||
moveComp.startPos.set(adjustedStartPos);
|
||||
moveComp.targetPos.set(adjustedTargetPos);
|
||||
node.setPosition(adjustedStartPos);
|
||||
|
||||
|
||||
// 设置旋转角度
|
||||
const dirForAngle = new Vec3();
|
||||
Vec3.subtract(dirForAngle, adjustedTargetPos, adjustedStartPos);
|
||||
@@ -113,12 +113,12 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
node.angle = angle;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case RType.fixed:
|
||||
// 固定起始位置
|
||||
node.setPosition(moveComp.startPos.x, node.position.y, 0);
|
||||
break;
|
||||
|
||||
|
||||
case RType.fixedEnd:
|
||||
// 固定结束位置
|
||||
node.setPosition(moveComp.targetPos.x > 360 ? 300 : moveComp.targetPos.x, moveComp.targetPos.y, 0);
|
||||
@@ -154,26 +154,26 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
}
|
||||
|
||||
update(entity: ecs.Entity): void {
|
||||
if(!smc.mission.play ) return;
|
||||
if(smc.mission.pause) return
|
||||
if (!smc.mission.play) return;
|
||||
if (smc.mission.pause) return
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
const skillView = entity.get(SkillView);
|
||||
|
||||
|
||||
if (!moveComp || !skillView || !skillView.node) return;
|
||||
|
||||
|
||||
// 更新移动进度
|
||||
const isMoving = moveComp.updateProgress(this.dt);
|
||||
|
||||
|
||||
if (isMoving) {
|
||||
// 更新节点位置
|
||||
skillView.node.setPosition(moveComp.currentPos);
|
||||
|
||||
|
||||
// 处理自动旋转(贝塞尔移动)
|
||||
if (moveComp.runType === RType.bezier) {
|
||||
this.updateRotation(skillView.node, moveComp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 检查移动完成
|
||||
if (moveComp.isCompleted && moveComp.autoDestroy) {
|
||||
// 根据结束类型决定是否销毁
|
||||
@@ -185,7 +185,7 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新节点旋转(用于贝塞尔移动)
|
||||
*/
|
||||
@@ -193,29 +193,29 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (moveComp.progress < 1) {
|
||||
// 计算下一帧的位置来确定方向
|
||||
const nextProgress = Math.min(moveComp.progress + 0.01, 1);
|
||||
const t = moveComp.isAccelerate ?
|
||||
(nextProgress * nextProgress * 0.7 + nextProgress * 0.3) :
|
||||
const t = moveComp.isAccelerate ?
|
||||
(nextProgress * nextProgress * 0.7 + nextProgress * 0.3) :
|
||||
nextProgress;
|
||||
const nextPos = v3(0, 0, 0);
|
||||
|
||||
|
||||
// 计算下一个位置
|
||||
const oneMinusT = 1 - t;
|
||||
const oneMinusTSquared = oneMinusT * oneMinusT;
|
||||
const tSquared = t * t;
|
||||
const twoOneMinusTt = 2 * oneMinusT * t;
|
||||
|
||||
nextPos.x = oneMinusTSquared * moveComp.startPos.x +
|
||||
twoOneMinusTt * moveComp.controlPoint.x +
|
||||
tSquared * moveComp.targetPos.x;
|
||||
|
||||
nextPos.y = oneMinusTSquared * moveComp.startPos.y +
|
||||
twoOneMinusTt * moveComp.controlPoint.y +
|
||||
tSquared * moveComp.targetPos.y;
|
||||
|
||||
|
||||
nextPos.x = oneMinusTSquared * moveComp.startPos.x +
|
||||
twoOneMinusTt * moveComp.controlPoint.x +
|
||||
tSquared * moveComp.targetPos.x;
|
||||
|
||||
nextPos.y = oneMinusTSquared * moveComp.startPos.y +
|
||||
twoOneMinusTt * moveComp.controlPoint.y +
|
||||
tSquared * moveComp.targetPos.y;
|
||||
|
||||
// 计算方向角度
|
||||
const direction = new Vec3();
|
||||
Vec3.subtract(direction, nextPos, moveComp.currentPos);
|
||||
|
||||
|
||||
if (direction.length() > 0.01) {
|
||||
let angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI);
|
||||
if (moveComp.scale < 0) {
|
||||
@@ -236,15 +236,15 @@ export class SMoveHelper {
|
||||
*/
|
||||
static setupMoveForSkill(entity: ecs.Entity, startPos: Vec3, targetPos: Vec3, s_uuid: number): void {
|
||||
let moveComp = entity.get(SMoveDataComp);
|
||||
|
||||
|
||||
if (!moveComp) {
|
||||
moveComp = entity.add(SMoveDataComp);
|
||||
}
|
||||
|
||||
|
||||
moveComp.startPos.set(startPos);
|
||||
moveComp.targetPos.set(targetPos);
|
||||
moveComp.s_uuid = s_uuid;
|
||||
|
||||
|
||||
// 从技能配置获取默认参数
|
||||
const skillConfig = SkillSet[s_uuid];
|
||||
if (skillConfig) {
|
||||
@@ -253,7 +253,7 @@ export class SMoveHelper {
|
||||
if (skillConfig.is_accel) moveComp.isAccelerate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查技能是否正在移动
|
||||
*/
|
||||
@@ -261,7 +261,7 @@ export class SMoveHelper {
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
return moveComp ? moveComp.isMoving : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取技能移动统计信息
|
||||
*/
|
||||
@@ -269,7 +269,7 @@ export class SMoveHelper {
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
return moveComp ? moveComp.getMoveStats() : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止技能移动
|
||||
*/
|
||||
|
||||
@@ -146,7 +146,7 @@ export class Skill extends ecs.Entity {
|
||||
if (node.isValid) node.destroy();
|
||||
return;
|
||||
}
|
||||
if (config.EType != EType.collision) {
|
||||
if (SView.endType != EType.collision) {
|
||||
const collider = node.getComponent(BoxCollider2D);
|
||||
if (collider) {
|
||||
collider.enabled = false
|
||||
@@ -174,8 +174,10 @@ export class Skill extends ecs.Entity {
|
||||
sMoveCom.targetPos.set(targetPos);
|
||||
sMoveCom.s_uuid = s_uuid;
|
||||
sMoveCom.scale = caster.node.scale.x < 0 ? -1 : 1;
|
||||
sMoveCom.runType = config.RType;
|
||||
sMoveCom.endType = config.EType;
|
||||
// runType/endType/speed/time 由 prefab 的 SkillView @property 决定,配置表同名字段仅作兜底
|
||||
sMoveCom.runType = SView.runType;
|
||||
sMoveCom.endType = SView.endType;
|
||||
sMoveCom.speed = SView.speed > 0 ? SView.speed : config.speed;
|
||||
sMoveCom.bezierStartHeight = config.bezier_start_y ?? sMoveCom.bezierStartHeight;
|
||||
sMoveCom.bezierMidHeight = config.bezier_mid_y ?? sMoveCom.bezierMidHeight;
|
||||
sMoveCom.bezierArc = config.bezier_arc ?? sMoveCom.bezierArc;
|
||||
@@ -183,12 +185,12 @@ export class Skill extends ecs.Entity {
|
||||
sMoveCom.atk_x = SView.atk_x;
|
||||
sMoveCom.atk_y = SView.atk_y;
|
||||
|
||||
if (config.EType === EType.timeEnd) {
|
||||
if (SView.endType === EType.timeEnd) {
|
||||
let sTimeCom = this.get(StimeDataComp);
|
||||
if (!sTimeCom) sTimeCom = this.add(StimeDataComp);
|
||||
sTimeCom.reset();
|
||||
sTimeCom.s_uuid = s_uuid;
|
||||
sTimeCom.totalTime = Math.max(1, config.time ?? 0);
|
||||
sTimeCom.totalTime = Math.max(1, SView.time > 0 ? SView.time : (config.time ?? 0));
|
||||
sTimeCom.hitInterval = Math.max(0.5, config.hitcd || 0);
|
||||
} else {
|
||||
const sTimeCom = this.get(StimeDataComp);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { _decorator, Animation, CCInteger, Collider2D, Contact2DType, UITransform, v3, Vec3 } from "cc";
|
||||
import { _decorator, Animation, CCFloat, CCInteger, Collider2D, Contact2DType, Enum, UITransform, v3, Vec3 } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||
@@ -22,6 +22,22 @@ export class SkillView extends CCComp {
|
||||
@property({ type: CCInteger })
|
||||
atk_y: number = 0
|
||||
|
||||
/** 运动类型:直线/贝塞尔/固定起点/固定终点(由 prefab 配置,优先级高于 SkillSet) */
|
||||
@property({ type: Enum(RType), tooltip: "技能特效运动类型" })
|
||||
runType: RType = RType.linear;
|
||||
|
||||
/** 消亡条件:动画结束/计时结束/碰撞次数结束(由 prefab 配置,优先级高于 SkillSet) */
|
||||
@property({ type: Enum(EType), tooltip: "技能特效消亡条件" })
|
||||
endType: EType = EType.collision;
|
||||
|
||||
/** 移动速度(由 prefab 配置,<=0 时回退 SkillSet.speed) */
|
||||
@property({ type: CCFloat, slide: true, range: [0, 2000, 10], tooltip: "技能特效移动速度" })
|
||||
speed: number = 0;
|
||||
|
||||
/** timeEnd 持续时间(秒),仅 endType=timeEnd 时生效(由 prefab 配置,<=0 时回退 SkillSet.time) */
|
||||
@property({ type: CCFloat, slide: true, range: [0, 30, 0.1], tooltip: "timeEnd 持续时间(秒)" })
|
||||
time: number = 0;
|
||||
|
||||
private debugMode: boolean = false;
|
||||
|
||||
anim: Animation = null;
|
||||
@@ -45,7 +61,7 @@ export class SkillView extends CCComp {
|
||||
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 = this.SConf?.EType === EType.collision;
|
||||
this.collider.enabled = this.endType === EType.collision;
|
||||
}
|
||||
if (this.node.getComponent(Animation)) {
|
||||
let anim = this.node.getComponent(Animation);
|
||||
@@ -128,13 +144,13 @@ export class SkillView extends CCComp {
|
||||
|
||||
onAnimationFinished() {
|
||||
// animationEnd 类型:动画结束后再关闭碰撞并销毁
|
||||
if (this.SConf.EType == EType.animationEnd) {
|
||||
if (this.endType == EType.animationEnd) {
|
||||
this.disable_collider_now();
|
||||
this.ent.destroy()
|
||||
return;
|
||||
}
|
||||
// fixed 类型不移动,无法通过移动完成销毁;动画播完作为兜底销毁时机
|
||||
if (this.SConf.RType == RType.fixed) {
|
||||
if (this.runType == RType.fixed) {
|
||||
this.disable_collider_now();
|
||||
this.ent.destroy()
|
||||
}
|
||||
@@ -142,7 +158,7 @@ export class SkillView extends CCComp {
|
||||
// 动画帧事件 atk:仅负责开启一帧碰撞窗口,不负责伤害与计数
|
||||
public atk(args: any) {
|
||||
if (!this.SConf) return;
|
||||
if (this.SConf.EType == EType.collision) return
|
||||
if (this.endType == EType.collision) return
|
||||
if (this.enable_collider_safely()) {
|
||||
mLogger.log(this.debugMode, 'SkillView', `[SkillView] [${this.SConf?.name}] 开启碰撞检测`);
|
||||
this.scheduleOnce(() => {
|
||||
|
||||
Reference in New Issue
Block a user