技能数据结构设计

发布时间:2026/10/24 7:26:46

技能数据结构设计 上一篇讲了数据和逻辑要分离把技能数值抽成配置。但真到动手设计配置结构的时候你会发现坑比想象的多。字段怎么定、效果怎么组织、目标怎么选……随便一个没想清楚后面就得推倒重来。这篇就把技能的数据结构一步步搭起来。从最天真的版本开始新手第一版通常长这样{id:fireball,name:火球术,damage:100,cooldown:3}能用但撑不了几天。策划马上会提各种需求把这个结构撑爆“火球术要有施法距离限制” → 加个range“要消耗 30 点法力” → 加个manaCost“命中后还要点燃每秒掉 5 血持续 3 秒” → 这咋加“有个技能是治疗队友不是打敌人” →damage变负数太别扭了你一路加字段结构越来越乱最后变成一个几十个字段的大杂烩一半技能用不上一半字段。这说明一开始就没分清楚哪些是所有技能都有的哪些是特定技能才有的。第一刀分出基础信息和效果任何技能都能拆成两部分。一部分是元信息——这个技能是什么比如名字、图标、冷却、消耗、施法距离。这些几乎每个技能都有是固定的框架。另一部分是效果——这个技能干什么比如造成伤害、治疗、加buff、击退。这部分千变万化是真正的核心。按这个思路重新设计{id:fireball,name:火球术,icon:fireball.png,cooldown:3,manaCost:30,range:8,effects:[{type:damage,value:100,element:fire}]}关键变化在于伤害不再是一个顶层字段而是塞进了effects数组里成为一个效果。这一步看着简单威力巨大。因为效果是数组一个技能就能挂多个效果{id:poison_blade,name:淬毒之刃,cooldown:5,effects:[{type:damage,value:50,element:physical},{type:dot,value:10,duration:3,element:poison},{type:slow,value:0.3,duration:2}]}一刀砍下去先扣 50 血再中毒每秒掉 10 持续 3 秒还减速 30%。全靠往数组里加效果一行代码不用写前提是这几种效果引擎都支持。第二刀效果要能描述打谁上面的结构还漏了关键一环——这些效果作用在谁身上火球术的伤害打敌人但同一个技能可能伤害敌人的同时治疗自己。所以每个效果都得说清楚自己的目标。给效果加上target字段{id:life_drain,name:生命汲取,cooldown:8,effects:[{type:damage,value:80,target:enemy},{type:heal,value:40,target:self}]}打敌人 80同时回自己 40。目标不同写清楚就行。目标类型常见的有这么几种提前定义好self 自己 enemy 单个敌人 allEnemies 范围内所有敌人 ally 单个队友 allAllies 所有队友第三刀效果要能描述什么时候触发再复杂一点的技能效果不是立刻全部生效的有先后、有条件。比如蓄力斩施法瞬间不掉血蓄力 2 秒后才爆发伤害。再比如处决只有当目标血量低于 30% 时才追加一段真实伤害。这就需要给效果加上触发时机和触发条件{id:execute,name:斩杀,cooldown:10,effects:[{type:damage,value:100,target:enemy,trigger:onCast},{type:damage,value:300,target:enemy,trigger:onHit,condition:{targetHpPercent:0.3}}]}第一段伤害固定 100施法就生效。第二段 300 的斩杀伤害只有命中时目标血量低于 30% 才触发。trigger定义在哪个时间点执行常见的onCast 施法瞬间 onHit 命中目标时 onTick 持续期间每秒 onEnd 效果结束时condition定义满足什么才执行是可选的不填就是无条件执行。拼起来看一个完整的技能结构长啥样把上面几刀合起来一个技能的完整数据结构大概是这样{id:flame_strike,name:烈焰打击,icon:flame_strike.png,description:对目标造成火焰伤害并点燃若目标已中毒则额外爆炸,cooldown:6,manaCost:40,range:10,castTime:0.5,effects:[{type:damage,value:120,element:fire,target:enemy,trigger:onCast},{type:dot,value:15,duration:4,element:fire,target:enemy,trigger:onHit},{type:damage,value:200,element:fire,target:enemy,trigger:onHit,condition:{targetHasBuff:poison}}]}结构清晰得一目了然上半部分是技能的框架信息下半部分是三个效果各自写明了作用对象、触发时机和触发条件。对应到代码里用类来接classSkillConfig{Stringid;Stringname;Stringicon;Stringdescription;floatcooldown;intmanaCost;floatrange;floatcastTime;ListEffectConfigeffects;// 核心效果列表}classEffectConfig{Stringtype;// damage / heal / dot / slow ...floatvalue;Stringelement;// 元素属性可选intduration;// 持续时间可选Stringtarget;// self / enemy / allEnemies ...Stringtrigger;// onCast / onHit / onTick ...MapString,Objectcondition;// 触发条件可选}一个容易翻车的点别把所有字段塞进一个类你可能注意到EffectConfig里有duration持续时间这种字段但纯伤害效果根本用不上它。字段一多就会出现伤害效果里躺着一堆治疗才用的字段这种尴尬。小项目无所谓字段多点就多点。但如果效果类型很多、差异很大可以考虑按类型拆分用多态abstractclassEffectConfig{Stringtarget;Stringtrigger;MapString,Objectcondition;}classDamageEffectextendsEffectConfig{floatvalue;Stringelement;}classDotEffectextendsEffectConfig{// 持续伤害floatvalue;intduration;Stringelement;}classHealEffectextendsEffectConfig{floatvalue;}这样每种效果只带自己需要的字段干净。代价是解析配置时要根据type判断该反序列化成哪个类稍微麻烦点。怎么选看你的效果种类多不多、字段差异大不大。再进一阶技能之间的复用做到后面你会发现很多技能长得像。比如一堆火系技能都是伤害 点燃只是数值不同。每个都完整写一遍还是有点冗余。这时可以引入模板或继承的思路让技能能复用一个基础配置{id:big_fireball,name:大火球,extends:fireball,// 继承火球术的所有配置overrides:{cooldown:5,effects[0].value:250// 只改伤害值}}不过这个要不要上得掂量。它确实减少了重复但也让配置变活了——你光看一个技能配置不去翻它继承的爹就不知道它最终长啥样排查问题变累。除非重复真的多到受不了否则老老实实每个技能写全反而更好维护。设计时记住这几条先分层再填字段。永远先把元信息和效果分开效果一定要设计成数组。这是整个结构的地基地基对了后面才好扩展。效果是核心把它做通用。一个效果至少要能回答三个问题干什么type value、对谁干target、什么时候干trigger/condition。把这几个维度定清楚绝大多数技能都能用配置拼出来。别一步到位设计太复杂。如果你的技能就是造成伤害这么简单那trigger、condition这些先别加等真有需求了再补。过度设计的结构维护起来一样痛苦。留好扩展口子但别提前实现。结构上给未来的效果类型留位置比如type用字符串而不是写死的枚举但没到那一步就别硬塞功能进去。一句话收尾技能数据结构设计核心就一句把技能拆成框架信息和效果列表让每个效果都能说清楚自己干什么、对谁干、什么时候干。框架保证所有技能长得规整效果数组保证任意技能都能自由组合拼装。结构设计好了前面那套数据逻辑解耦才能真正落地——策划在配置表里拼效果程序员在引擎里实现效果各司其职谁也不耽误谁。
延伸阅读

更多相关文章

2026/10/23 21:19:35

Tiny:3行代码把Android图片压到2.3%

Tiny:3行代码把Android图片压到2.3% 【免费下载链接】Tiny an image compression framework.(一个高保真、高压缩比的图片压缩框架) 项目地址: https://gitcode.com/gh_mirrors/ti/Tiny Tiny是Android图片压缩框架,把6.66M…

2026/10/24 7:23:41

深度学习人脸识别毕设全流程:从数据集到系统落地

人脸识别这四个字,放在毕设选题里属于那种“看起来门槛不高、真做起来处处是坑”的典型。每年到这个季节,总有一批同学拿着“深度学习机器视觉人脸识别系统”这个题目来找我聊,问题高度集中:数据集怎么搞、模型选哪个、为什么自己…

2026/10/24 7:23:41

深度学习人脸识别系统毕设实战:从架构设计到演示避坑

1. 项目缘起与整体设计思路拆解每年到了毕设季,后台总有一批人问我同一个问题:想做一个人脸识别的深度学习项目,但不知道从哪下手,网上代码一搜一大把,跑起来全是报错,改都不知道从哪改。这个项目标题看着简…

2026/10/24 7:23:41

Spark批处理性能优化实战:从数据倾斜到参数调优

1. 问题背景:当Spark批处理遇上性能瓶颈去年接手公司数据平台时,我遇到了一个典型的Spark批处理性能问题:每天凌晨运行的报表生成作业,处理约2TB的原始日志数据,从最初的3小时逐步恶化到接近5小时完成。这不仅影响了早…

2026/10/24 7:23:41

Multimodal Pathway:多模态融合通路设计与调优

去年下半年我接手了一个内部系统的改造需求,要把图像、文本和一小段语音信号塞进同一个模型里做联合判断。数据量不小,标注质量也还行,单模态的指标都挺漂亮,可一旦拼到一起,整体效果反而比只用文本还差一截。排查了两…

2026/10/24 7:23:41

Kubernetes资源清单编写指南与最佳实践

1. Kubernetes资源清单入门指南刚接触Kubernetes时,最让我困惑的就是那些YAML文件——它们看起来简单,但实际写起来总是报错。资源清单(Manifest)是Kubernetes世界的"施工图纸",它用声明式语法告诉集群你想要什么样的资源状态。经过…

2026/10/24 7:18:41

YOLO自动标注工具实战:预标注、格式校验与增量标注

简介:面向YOLO系列目标检测训练的数据标注工具,适合需要快速构建数据集的研究人员、学生与开发者,重点解决手工框选耗时、标注格式不统一的问题。压缩包共115个文件,约6.3MB,以42个png界面/示例图、29个py源码、9个svg…

2026/10/23 22:56:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/24 0:02:40

MATLAB缩进快捷键与批量格式化实战指南

1. 被自动缩进折磨的那些年如果你写过MATLAB代码,大概率经历过这种场景:从某个文档、网页或者聊天记录里复制了一段代码,粘贴进编辑器之后,每一行前面都带着莫名其妙的空格,有的行首是四个空格,有的是一个T…

2026/10/24 0:02:40

用Poco实现Qt风格信号与槽的跨平台C++方案

简介:本资源是一份面向C中级开发者的技术实践工程,聚焦于在非Qt框架环境下模拟实现Qt核心通信机制——信号与槽,借助Poco网络库的事件系统完成解耦式对象通信。适用于需在跨平台C项目中引入松耦合回调机制、但受限于无法集成Qt依赖的开发场景…

2026/10/24 0:02:40

ESXi裸机虚拟化安装指南:从硬件兼容到虚拟机部署

1. 为什么还要折腾ESXi:从一台闲置机器说起手里攒了几台淘汰下来的迷你主机,配置不算差,i5加16G内存,扔了可惜,装个桌面系统又觉得浪费。这种场景下,ESXi就成了一个绕不开的选择。它是一套裸机虚拟化平台&a…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑