网易首页 > 网易号 > 正文 申请入驻

独立游戏-战斗系统开发构建

0
分享至

【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!

这是侑虎科技第1621篇文章,感谢作者Jamin供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)

作者主页:

https://www.zhihu.com/people/liang-zhi-ming-70

背景

写这篇文章的背景来自于去年做的一款《星穹铁道》的战斗模拟器,可在B站搜索【耗时3个月,自制星铁战斗系统!就为作出最强攻略!】查看 。

后来结合自身经验又将此战斗系统扩展复用到了多种类型的游戏Demo中。在此来简单总结分享下其中组成,也不期待能帮助到大家什么,仅当在如今游戏行业的氛围中聊以慰藉吧。

做这个模拟器的背景在视频里其实有交代的蛮清楚的,感兴趣的会看不感兴趣的也不用多介绍了。来说一下实现了什么样的功能:

1. 完全模拟了《星穹铁道》(卡牌向)的所有核心战斗机制,技能体系、数值体系、能量、装备系统、行动出手逻辑等。

2. 截止xx前所有角色战斗逻辑(和官方技能描述一致)。

3. 实现了随机/伪随机的可重入操作(也就是视频里经常提到的万次模拟)。

4.伤害公式数值公式、甚至Buff被动等时序以及打出来的伤害和官方角色实际体验保持一致

5. 截止xx前完全拆解并实现了当前版本的所有特殊角色的特殊逻辑。

6. 加了点前端界面,有战斗过程、出手演示行动演示数据LOG演示调试等界面。

为什么要从卡牌讲起?

  • 因为这是我个人经历中比较少见的给“自己”“商用”的战斗体系搭建,是从0开始搭建成功落地验证了扩展性的结构。因为平时就热爱游戏开发,这套战斗体系我同样移植给了自己做的“音游”、“肉鸽”、“休闲游戏”、“割草游戏”等多个Demo中。所以其实可以看到这并不局限于游戏类型,只要维护核心观念的扩展性即可(配置驱动)。

概览下战斗系统里包含什么?

  • 战斗核心机制是“技能”、“Buff”、“子弹”体系的三者联动, 辅以“被动”、“装备”、“法球”等机制用来配合实现特定逻辑。

  • 逻辑与表现分离:这是避免不同步的基础,也是后续万次重入结论一致的基础,在设计之初就应该考虑的。

  • C#配置表工具:在工作中有做了一个把Excel表导出成C#数据表的工具,生成C#之后可以让代码里直接调用对应的Excel类的属性,所见即所得可以说非常好用了。

  • 出手逻辑:也就是程序如何循环的。这里不同类型的游戏会定制化一些。

  • 伤害机制:伤害公式确认好之后,重点就是用Buff和属性、被动等共同组织起各种加成与时序算法。

  • 人物属性:单独拿出来说是因为人物属性需要做到动静分离,实时变更。影响因素较多(如装备、被动、Buff等),做到高效组织是需要点功力在的。

  • 触发机制:其实大部分就是被动带来的,注册+触发执行。

  • 日志系统:包含及其丰富细致的日志系统,让所有数据有迹可循。

  • 战斗表现:Demo做的粗糙,真正商业化游戏配合着技能编辑器来,根据时间轴做好战斗前摇、出手、后摇阶段的排版。

  • 操作手感:这是我最擅长的部分,单独拿出来作为一个文章不为过,解决过王者上千个战斗Bug,走A、寻敌、位移、指示器等等非常多,也感慨优化了大部分的英雄。

  • 打击感:抛砖引玉:技能缓存、飘字、震动、血条表现、顿帧、硬直等等。

  • 音频:不是我关注的重点,但是玩家体验的关键一环。

  • 网络:帧同步|状态同步。

  • Debug:快捷的调试工具也是节约开发时间的“利器”。

  • 渲染表现:风火雷电冰、雨雪阴晴、草水等等,不作为本文重点。

  • AI:本身AI&怪物AI。

  • UI:战斗UI,可能讲一下有趣的地方,比如3DUI、资源后处理Event生成等。

  • 资源加载:和战斗关联比较大,顺便提一下。

战斗系统雏形构建思路(《星穹铁道》为例)

这是写给我自己做的独立游戏的,并不适用于所有项目/大厂,正式的战斗系统会更为复杂严谨,各位资深道友看见了觉得写的草率了就图一乐吧。

下面的内容组织思路?

从《星穹铁道》战斗系统的整体构建来总览回顾一步步还原从0制作一款卡牌战斗雏形的过程。

1. 首先构建初始时序

2. 讲一下个人风格战斗体系的组成,重点是如何实现高扩展性

3. 讲一下战斗相关系统扩展,比如战斗表现|日志系统|资源加载等。

4. 将战斗系统扩展应用到多类型游戏中,验证扩展性和鲁棒性。

构建初始时序

根据游戏类型(卡牌),做了下出手执行顺序的草图,这是游戏运转前的基础验证,后续的所有战斗逻辑皆以此为基础扩展。

可以看到《星穹铁道》的核心出手机制定义为行动值,其实行动值就是速度,每个角色在程序中的运行速度的差异决定了普攻出手的先后。然后辅以每个角色特殊的战技出手条件&能量出手条件,形成了一个角色全部的行动规则

下面提供角色更新伪代码(为常规模拟模式稍微做了些2D表现,所以使用了协程wait.):

// 通过协程分帧处理表现
public IEnumerator ExcuteInner()
{
// 前置需要添加Boss | 角色 | 日志系统 | 开局事件触发等
var maxRunCount = 全局配置表["行动值上限"];

while (curRunCount++ < maxRunCount)
{
// 更新人物
foreach (var actor in actorList)
{
actor.Update();
yield return new WaitForSeconds(0.5f);
}

// 更新怪物 or 对手等..
yield return new WaitForSeconds(0.01f);
}
}

角色出手逻辑伪代码:

public void Update()
{
// 判断死亡,死亡不会执行后续
if (IsDie()) return;

// 更新角色携带的宠物
m_pet?.UpdatePet();

// 更新人物路程
ChangeWay(speed);

// 检查大招释放规则(能量更新在角色出手外,可以做到差帧更新: 即大招能量条满了不会同帧抢技能执行)
CheckPlayEnergySkill();

// 判断是否可以出手(当前行动路程大于预设)
if (m_curWay >= GlobalConfig.S_SumWay)
{
// 回合开始事件等派发
EventCenter.Instance().Notify(EVENT_NAME.ROUND_BEGIN, this, arg);

// 路程归零(这里可以加速度余量,没加大概是强度使然)
SetWay(0);

// 更新持续伤害
UpdateLastDamageBuffs();

// 判断是否存在冻结等行动停滞效果
if (IsFrozen())
{
// 冻结之后路程变成5000后面且不会出手,但是可以触发buff
}
else
{
ActorFight();
}

// 检查大招释放规则
CheckPlayEnergySkill();

// 更新Buff(挂在角色身上的正面负面都算)
UpdateBuffs();

// 更新被动技能
UpdatePassiveSkills();

// 清理当前轮次的攻击对象等回合相关信息
// ClearRoundData();
}

// 移除延迟buff列表(有些buff不会在当前更新即刻移除,要放在DelayRemoveBuff列表中延迟移除)
// 移除被动(同理)
// 角色更新完成
}

补充ActorFight判断是否是战技出手即完成完整角色出手流程:

public void ActorFight()
{
// 敌人出手前更新韧性
// 出手前判断buff列表是否有回合开始时需要执行的buff
for (int i = 0; i < m_buffList.Count; i++)
{
buffExcuteDic[m_buffList[i].m_buffType].RoundBeginExcute(m_buffList[i]);
}

// 判断技能出手条件是否满足 决定此刻是普攻/战技出手
if (!CanSkill())
{
PlayAttack();
}
else
{
PlaySkill();
}
}

构建角色属性系统

角色属性是伤害公式调用的基础,伤害公式就是根据配置动态修改各种属性的业务算法,而各种属性又决定了玩家的游戏策略,所以这个时候可以优先选择构建属性系统。

以《星穹铁道》早期的人物属性举例,可以拆解为:

速度、阵营、角色类型、攻击力、增伤、伤害加成、暴击率、无视防御、防御、暴击加成、血量、等级、穿透、抗性、韧性、嘲讽值、最大能量值、攻击属性、弱点、抗性弱点。

下面这个配置表也可以参考一二,为什么用的是拼音啊?Up是我室友他学俄语的啊!!!要蚌埠住了,实在没有勇气用俄语来做表头和代码注释,索性在部分属性上折个中用拼音了。

后来才悔恨地加了一 行中文注释.. 晚了

这里有3个点:

Q:为什么是会出现5000这种数字?

A:为了保证精度,用万分比保留2位小数部分。

Q:为什么是会出现大面积的0?

A:0代表了角色身上的初始属性确实没有,但是可以支持后续带有特定属性的角色更新。

Q:为什么逻辑上又出现中文?

A:不用怕,针对有强迫症的程序来讲,是准备了一张中文转换表的,可以将中文适配成对应的枚举,但是给“策划”展示依然是中文方便阅读配置(不然你填个2谁知道是什么)。

至此,关于属性的基础创建就完成了,选择了对应的角色就可以直接使用属性系统了。

构建装备系统

本来不想扩散的,不过上一章节配置表中有很多的0,看不习惯,那就增加一个章节讲一下属性系统的实际数值是如何填充的(其中一种方式)- “装备系统的构建”。这一节很短,快的离谱。

Q:装备很多、属性很杂、还有装备各种特殊效果、套装加成等,关于加成的配置和装备的代码一定很麻烦吧?

A:核心代码几十行代码就搞定,只需要“通用的属性加成”与“被动添加移除机制”,下面提供伪代码:

// 获取装备属性
public int GetEquipAdd(PropertyType _property)
{
// 自行判空 异常处理

return m_configData[propertyType];
}

// 添加被动
public void AddPassiveSkill()
{
// 自行判空 异常处理
var passiveID = m_configData["PassiveID"];

foreach (var p in passives)
{
if (p > 0)
{
// 参数分别代表: 1.给谁上被动 2.谁上的被动 3.被动的id
UTils.AddPassive(m_srcActor, m_srcActor, p);
}
}
}

// 移除被动
public void Remove()
{
// 自行判空 异常处理
var passiveID = m_configData["PassiveID"];

foreach (var p in passives)
{
if (p <= 0)
{
continue;
}

if (m_srcActor.ContainsPassive(p))
{
m_srcActor.RemovePassive(p);
}
}
}

装备的配置加成属性其实可玩项【非常丰富】

至此,已经讲完属性系统与装备填充的部分,接下来关注比较核心的伤害公式部分(每个游戏此部分应不尽相同,特别是成长类型游戏,是数值策划保证游戏生命周期的必修课)。

根据伤害公式构建伤害系统

来拆解一下伤害公式(早期的部分伤害公式中文描述,后续我们是有微调迭代的,每一种伤害公式我们后期都和原版游戏运行进行了大量对比验证)。

关于伤害公式的选择有非常多种,这里因为复刻的《星穹铁道》就以《星穹铁道》的公式为引子介绍,其余公式可以根据情况自行推导。

《星穹铁道》的伤害公式是乘法公式DMG=a*ATK*F(targetDEF),这种公式可以形容为“折损伤害”,比较适合ATK与DEF的成长空间无限大(无限成长扩展那种),通过构建F(DEF),可以得到边界递减的收益效果:

示意

简单知道了公式原理后,我们来拆解一下《星穹铁道》存在哪些伤害公式(有十多种,不一一截全了,早期Demo期间推导的战斗公式需求表,内容在后续实战测试验证后有调整)。

《星穹铁道》伤害公式在早期模拟系统Demo期间的拆解示意图

这里大家可以看到,正式游戏中的伤害公式不止一种,为了增加游戏的复杂多变性,往往就需要增加各种打破常规的计算方式来增加伤害的数值乐趣。这点如果是做独立游戏的,可以根据平衡性自己设计,或者就完全拆解已经被验证过数值曲线的数值公式。

接下来来看战斗机制部分。

战斗体系的核心组成

核心为技能、Buff和子弹的组织循环,再加入“被动”、“印记”、“法球”等效果,基本可以实现“所有”想象的到的战斗技能效果。

技能系统 简易示意图

如何实现高扩展性?

这套体系的优势就在高扩展性,将逻辑原子化提供节点给“策划”调用,扩展参数以达到强大的复用效果。

在B站的评论区经常有人会问:米哈游再出一个英雄,你是不是要重新全部实现一次英雄的技能呢?如果是这样,累也怕是累死了,《星穹铁道》战斗团队十数人一个版本的内容我完全手敲代码复刻要死的。

如何做到的?两点:

1. 技能配置文件

2. 优秀的抽象逻辑节点

技能配置文件

这部分既是指技能编辑器产出的技能组成,也同样指我们技能表中的配置。那为什么会存在两份结构不一样的配置表呢?一个比较直观的解释:技能配置表更像是数据库,你可以随时读取数据。技能配置文件则是组织技能出手后的复杂执行逻辑&效果的配置文件。他们的核心都为“数据驱动”,所以也可以说,只要做到了足够丰富抽象的节点设计,使用“数据驱动”就可以让策划自己编排所有后续的战斗需求了。

技能配置表

技能配置表单拿出来是因为大家基本都会使用的到,一般也会转成二进制数据而存在。这里我想为小团队/独立游戏制作者推荐一个个人制作的C#转表工具。

实现的原理很简单就不讲了,有需要的我可以把工具贴到Git上。

使用结果上可以将配置表的数据转成C#类中清晰可见的数据结构并且有相应数据填充,实现了C#类的配置表信息存储。适用于小团队是因为其足够的方便,导出后可以在业务侧直接使用对应配置表类的数据。并且点击类名可以跳转到对应类中查看所有有效数据减少查看原始Excel的繁琐操作,更改临时数据更是可以做到1s搞定

下面是C#配置表的示例(原始数据为Excel表,为了避免不必要的麻烦使用的是自己的Demo游戏配置数据):

技能配置表相关数据

public partial class NCONFIG_CSHAP
{
public static Dictionary CfgBuff = new Dictionary
{
[100101] = new CfgBuffData {
ID = 100101,
Name = "通用伤害",
Desc = "测试",
SkillSrc = "XX技能",
LastTime = 1f,
BuffType = "通用伤害",
Param1 = 0,
Param2 = 0,
Param3 = 0,
PerCentParam = 10000,
target = "对方单体",
BuffTypeAddBuff = 0,
LastBuff = false,
DieJia = "",
MaxCount = 1,
DelayBuff = false,
TriggerCD = 0,
EndAddBuffs = new int[] { },
},
[100102] = new CfgBuffData {
ID = 100102,
Name = "普通攻击伤害",
Desc = "测试",
SkillSrc = "XX技能",
LastTime = 1f,
BuffType = "通用伤害",
Param1 = 0,
Param2 = 0,
Param3 = 0,
PerCentParam = 30000,
target = "对方单体",
BuffTypeAddBuff = 0,
LastBuff = false,
DieJia = "",
MaxCount = 1,
DelayBuff = false,
TriggerCD = 0,
EndAddBuffs = new int[] { },
},
}
}

抽象逻辑节点

当建立了一定体量的逻辑功能节点后,“策划”就可以通过简单改变配置来组合达到不同的技能效果了。

在讲之前,可以先分析以下两个技能的区别:

1. 释放技能,对随机敌人造成x点伤害,并叠加一层火焰伤害,每回合每层火焰伤害造成x点伤害,最高上限5层。

2. 释放技能,对选中敌人造成五段冰霜伤害,最后一段伤害必定造成暴击。

这两个技能看起来风马牛不相及,实际上同属【伤害】这个概念中。我们可以从技能描述中抽离出“随机/选中敌人”、“火焰/冰霜”、“单回合/多回合”、“1段/5段伤害”、“暴击”这些差异点。

那我们只需要构建一个通用的伤害Buff,在执行的过程中根据以上五种差异元素做配置判断即可,根据配置:

  • 选敌逻辑抽象出来:可以选择单个、多个、随机的敌人。可以选择血量最低、伤害最高、距离最近的友军。

  • 元素逻辑抽象出来:可以配置冰、火、暗、光属性等,并单独结算属性伤害&韧性计算(关于破韧等逻辑使用条件触发即可)。

  • 回合逻辑抽象出来:控制生命周期,根据配置单回合生效即销毁还是执行多回合。

  • 叠加逻辑抽象出来:分段伤害可以分为几种:

    • 如果是纯伤害叠加可以使用Buff叠层

    • 如果要分开结算(比如暴击率独立判定),则配置多个伤害Buff,或者Buff执行衔接Buff等方式都可以。

  • 暴击逻辑抽象出来:配置可以无极调整的暴击率参数就可以。

用来简化的表达如下:技能产生Buff,Buff通过配置表参数传递特殊数据,而具体的执行逻辑节点是注册机制,使用Map索引即可。

Buff执行节点示意

通用Buff逻辑执行节点注册示意

具体逻辑节点要做的事情千变万化,也是高扩展性的核心竞争力 。这里就不展开讲了,注意配置的扩展就好。

文末,再 次感谢 Jamin 的分享, 作者主页: https://www.zhihu.com/people/liang-zhi-ming-70,关于文章的更多探讨,也可添加作者微信(15145089910)进行交流。 如果您有任何独到的见解或者发现也欢迎联系我们。

近期精彩回顾

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
福建舰入列第3天,郑丽文代表国民党,作出一个事关两岸重要承诺

福建舰入列第3天,郑丽文代表国民党,作出一个事关两岸重要承诺

健身狂人
2025-11-09 00:30:18
微信出手:集体下架!

微信出手:集体下架!

中国基金报
2025-11-08 22:46:52
1994年,89岁石油大亨娶26岁脱衣舞女郎,新婚14个月石油大亨去世

1994年,89岁石油大亨娶26岁脱衣舞女郎,新婚14个月石油大亨去世

百态人间
2025-11-05 05:20:03
开拓者队记:杨瀚森迅速跌出轮换阵容,当初选他的意义何在?

开拓者队记:杨瀚森迅速跌出轮换阵容,当初选他的意义何在?

狼叔评论
2025-11-08 12:58:03
全运会男足:上海U20 3-2新疆U20,刘诚宇、蒯纪闻破门,李新翔绝杀

全运会男足:上海U20 3-2新疆U20,刘诚宇、蒯纪闻破门,李新翔绝杀

懂球帝
2025-11-08 22:25:03
汽水音乐用户量狂飙超1.2亿 QQ音乐、网易云音乐有压力了

汽水音乐用户量狂飙超1.2亿 QQ音乐、网易云音乐有压力了

快科技
2025-11-07 11:22:06
世界杯附加赛即将揭幕!22队争夺6席,意大利与葡萄牙或提前交锋?

世界杯附加赛即将揭幕!22队争夺6席,意大利与葡萄牙或提前交锋?

山河入画屏
2025-11-08 11:30:51
成“老赖”不到72小时,于谦资产被扒底朝天,杨议的话有人信了

成“老赖”不到72小时,于谦资产被扒底朝天,杨议的话有人信了

科学发掘
2025-10-31 14:06:52
全运会赛程日历来了!

全运会赛程日历来了!

北青网-北京青年报
2025-11-08 13:39:05
嫩妇自述:和老公分居后,我每天去健身房练臀,却被私教给盯上了

嫩妇自述:和老公分居后,我每天去健身房练臀,却被私教给盯上了

想养大熊猫
2024-05-08 10:04:15
全运会男篮八强出炉:四川vs北京 广东vs天津

全运会男篮八强出炉:四川vs北京 广东vs天津

体坛周报
2025-11-08 21:51:11
有个非常不妙的消息,中国可能在新货币战争中遇到麻烦了。

有个非常不妙的消息,中国可能在新货币战争中遇到麻烦了。

流苏晚晴
2025-11-08 17:07:59
恒大幕后黑手曝光:刚被“抄家”的许家印,很可能是只“替罪羊”

恒大幕后黑手曝光:刚被“抄家”的许家印,很可能是只“替罪羊”

史行途
2025-11-01 11:40:29
刚刚证实!TVB老戏骨凌汉去世,曾参演《唐伯虎点秋香》

刚刚证实!TVB老戏骨凌汉去世,曾参演《唐伯虎点秋香》

鲁中晨报
2025-11-08 16:11:02
国米本赛季错失28次绝佳机会,图拉姆、劳塔罗、皮奥合计15次

国米本赛季错失28次绝佳机会,图拉姆、劳塔罗、皮奥合计15次

懂球帝
2025-11-09 00:06:28
Prada别针式胸针门店售价近6000元,网友:比黄金还贵!Prada门店:暂无现货可调货

Prada别针式胸针门店售价近6000元,网友:比黄金还贵!Prada门店:暂无现货可调货

极目新闻
2025-11-08 15:14:29
潜伏在我国高层的四大间谍,被安插在军政两界,导致我国损失惨重

潜伏在我国高层的四大间谍,被安插在军政两界,导致我国损失惨重

阅识
2025-10-28 15:23:15
知道怕了?白应苍被判死刑,吓坏了沈伯洋,美国不搭理,求助无门

知道怕了?白应苍被判死刑,吓坏了沈伯洋,美国不搭理,求助无门

科普100克克
2025-11-08 13:15:20
突然火了!年轻人捡漏倒闭车企“烂尾车”,有人半价买哪吒,有人12万元抄底高合,“开10万公里就回本了”

突然火了!年轻人捡漏倒闭车企“烂尾车”,有人半价买哪吒,有人12万元抄底高合,“开10万公里就回本了”

每日经济新闻
2025-11-08 23:16:08
负1层起火,遇难的16人为什么全部集中在5层?央视披露四川自贡九鼎大楼火灾事故细节——

负1层起火,遇难的16人为什么全部集中在5层?央视披露四川自贡九鼎大楼火灾事故细节——

鲁中晨报
2025-11-07 20:11:05
2025-11-09 02:15:00
侑虎科技UWA incentive-icons
侑虎科技UWA
游戏/VR性能优化平台
1514文章数 985关注度
往期回顾 全部

游戏要闻

猎魂世界:朱竹清改版神赐实测报告!最弱到最强就只需这一改动?

头条要闻

张家界荒野求生选手抓到野猪吃得满嘴流油 赛事方回应

头条要闻

张家界荒野求生选手抓到野猪吃得满嘴流油 赛事方回应

体育要闻

马刺绞赢火箭,不靠文班亚马?

娱乐要闻

古二再度放料!秦雯王家卫吐槽出现新人物

财经要闻

小马、文远回港上市 但自动驾驶还没赢家

科技要闻

美股“AI八巨头”单周市值损失8000亿美元

汽车要闻

特斯拉Model Y后驱长续航版上线:28.85 万元

态度原创

健康
游戏
艺术
亲子
军事航空

超声探头会加重受伤情况吗?

网友问"10亿能私联吗"急坏小高和刚:日元还是人民币?

艺术要闻

1008米!世界新第一高楼项目,迎来第三家中国公司加入

亲子要闻

亲子健身运动,这样练习,增强感统训练!

军事要闻

福建舰常驻地为三亚军港

无障碍浏览 进入关怀版