refactor(skill): 重构技能配置加载逻辑,将参数下沉至prefab配置
1. 新增SkillView组件属性runType/endType/speed/time,替换原配置表字段 2. 批量同步所有技能prefab的配置参数 3. 优化技能运行逻辑,优先使用prefab配置,配置表仅作兜底 4. 新增同步脚本用于批量迁移技能配置
This commit is contained in:
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -108,8 +108,8 @@
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1.6,
|
||||
"y": 1.4,
|
||||
"x": 1.3,
|
||||
"y": 1.1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
@@ -252,7 +252,11 @@
|
||||
"__id__": 11
|
||||
},
|
||||
"atk_x": 20,
|
||||
"atk_y": 30,
|
||||
"atk_y": 40,
|
||||
"runType": 2,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
|
||||
@@ -282,7 +282,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 25,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -282,7 +282,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 25,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -282,7 +282,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 25,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -253,7 +253,11 @@
|
||||
},
|
||||
"atk_x": 0,
|
||||
"atk_y": 0,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -389,7 +389,11 @@
|
||||
},
|
||||
"atk_x": 0,
|
||||
"atk_y": 0,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 0,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
|
||||
@@ -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";
|
||||
@@ -40,8 +40,8 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据配置设置移动速度与加速度
|
||||
if (skillConfig.speed > 0) {
|
||||
// 移动参数由 prefab 的 SkillView @property 决定(speed<=0 时 Skill.load 已回退配置表值)
|
||||
if (moveComp.speed <= 0) {
|
||||
moveComp.speed = skillConfig.speed;
|
||||
}
|
||||
if (skillConfig.is_accel) {
|
||||
@@ -65,7 +65,7 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
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(
|
||||
@@ -154,8 +154,8 @@ 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);
|
||||
|
||||
@@ -205,12 +205,12 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const twoOneMinusTt = 2 * oneMinusT * t;
|
||||
|
||||
nextPos.x = oneMinusTSquared * moveComp.startPos.x +
|
||||
twoOneMinusTt * moveComp.controlPoint.x +
|
||||
tSquared * moveComp.targetPos.x;
|
||||
twoOneMinusTt * moveComp.controlPoint.x +
|
||||
tSquared * moveComp.targetPos.x;
|
||||
|
||||
nextPos.y = oneMinusTSquared * moveComp.startPos.y +
|
||||
twoOneMinusTt * moveComp.controlPoint.y +
|
||||
tSquared * moveComp.targetPos.y;
|
||||
twoOneMinusTt * moveComp.controlPoint.y +
|
||||
tSquared * moveComp.targetPos.y;
|
||||
|
||||
// 计算方向角度
|
||||
const direction = new Vec3();
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
83
tools/sync-skill-prefab.js
Normal file
83
tools/sync-skill-prefab.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 一次性迁移脚本:把 SkillSet 中的 RType/EType/speed/time 刷入各技能 prefab 的 SkillView 序列化字段。
|
||||
* 用法: node tools/sync-skill-prefab.js
|
||||
* 注意: 直接改写 prefab JSON,运行前请保证工作区已提交。
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const SKILL_SET = path.join(ROOT, 'assets/script/game/common/config/SkillSet.ts');
|
||||
const PREFAB_DIR = path.join(ROOT, 'assets/resources/game/skill/atk');
|
||||
// SkillView 组件在 prefab 中的脚本类 cid
|
||||
const SKILL_VIEW_CID = '57aabs7TE1J5obTAZczc+64';
|
||||
|
||||
const RTYPE = { linear: 0, bezier: 1, fixed: 2, fixedEnd: 3 };
|
||||
const ETYPE = { animationEnd: 0, timeEnd: 1, collision: 2 };
|
||||
|
||||
/** 从 SkillSet.ts 解析 sp_name -> {runType, endType, speed, time} */
|
||||
function parseSkillSet(src) {
|
||||
const map = new Map();
|
||||
// 匹配每个技能条目块
|
||||
const entryRe = /\d+:\s*\{([\s\S]*?)\n\s*\},/g;
|
||||
let m;
|
||||
while ((m = entryRe.exec(src)) !== null) {
|
||||
const body = m[1];
|
||||
const sp = body.match(/sp_name:\s*"([^"]+)"/);
|
||||
if (!sp) continue;
|
||||
const spName = sp[1];
|
||||
|
||||
const rt = body.match(/RType:\s*RType\.(\w+)/);
|
||||
const et = body.match(/EType:\s*EType\.(\w+)/);
|
||||
const speed = body.match(/speed:\s*([\d.]+)/);
|
||||
const time = body.match(/\btime:\s*([\d.]+)/);
|
||||
|
||||
const entry = {
|
||||
runType: rt ? RTYPE[rt[1]] : undefined,
|
||||
endType: et ? ETYPE[et[1]] : undefined,
|
||||
speed: speed ? Number(speed[1]) : undefined,
|
||||
time: time ? Number(time[1]) : 0,
|
||||
};
|
||||
// 多个技能可共用同一 sp_name,保留首个非 undefined 组合
|
||||
if (!map.has(spName)) map.set(spName, entry);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const src = fs.readFileSync(SKILL_SET, 'utf8');
|
||||
const confMap = parseSkillSet(src);
|
||||
|
||||
const files = fs.readdirSync(PREFAB_DIR).filter(f => f.endsWith('.prefab'));
|
||||
const report = { updated: [], skipped: [], noConf: [] };
|
||||
|
||||
for (const file of files) {
|
||||
const spName = path.basename(file, '.prefab');
|
||||
const conf = confMap.get(spName);
|
||||
const fp = path.join(PREFAB_DIR, file);
|
||||
const json = JSON.parse(fs.readFileSync(fp, 'utf8'));
|
||||
|
||||
// 定位 SkillView 组件
|
||||
const comp = json.find(o => o && o.__type__ === SKILL_VIEW_CID);
|
||||
if (!comp) { report.skipped.push(file + ' (no SkillView)'); continue; }
|
||||
|
||||
if (!conf) { report.noConf.push(file); continue; }
|
||||
|
||||
if (conf.runType !== undefined) comp.runType = conf.runType;
|
||||
if (conf.endType !== undefined) comp.endType = conf.endType;
|
||||
if (conf.speed !== undefined) comp.speed = conf.speed;
|
||||
comp.time = conf.time ?? 0;
|
||||
|
||||
fs.writeFileSync(fp, JSON.stringify(json, null, 2) + '\n', 'utf8');
|
||||
report.updated.push(`${file} -> runType=${comp.runType} endType=${comp.endType} speed=${comp.speed} time=${comp.time}`);
|
||||
}
|
||||
|
||||
console.log('=== updated ===');
|
||||
report.updated.forEach(s => console.log(' ' + s));
|
||||
console.log('=== no config matched ===');
|
||||
report.noConf.forEach(s => console.log(' ' + s));
|
||||
console.log('=== skipped ===');
|
||||
report.skipped.forEach(s => console.log(' ' + s));
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user