《高等元素论》 从程序实现的角度分析和复刻原神的元素反应系统
最近用了一周时间仔细学习了各个版本的高等元素论文字和视频教材,感觉目前的教材都是从玩家的角度描述现象和尝试用玩家容易认知的方式去归纳里面的原理,还充斥着各种科研名词,让这个系统可能变得比它实际的样子更复杂。
所以我有兴趣从代码实现的角度去分析什么样的系统框架可以更优雅的实现现有的表现,同时希望能抛砖引玉,让各位玩家有机会换一个角度穿过现象看本质。
注意,这篇文章需要一定的游戏制作知识,不然可能稍微难懂(蛋定,我不是专业程序,会尽可能用一般概念描述逻辑)

先说结论:我目前构造出的系统因为工作量原因暂时只实现了冰火雷水四个元素的相互反应,但目测是可以实现所有元素的反应的,而且和原版效果相差无几。
代码和可运行的DEMO:https://github.com/realamex/GenshinElement

核心思路
1、元素本质应该是一种BUFF(不像一般BUFF,元素没有固定结束时间,而是通过元素量什么时候衰减到0决定结束附着),那么如果有一个成熟的BUFF系统再做元素会方便很多,但我手上没有,所以只能随便写个勉强够用的凑合
2、反应是两两元素触发时生成的对象,在这个对象里定义什么元素组合(包括先后手顺序)可以触发这个反应,以及触发反应时有什么事情发生(也可以套娃,在反应时生成新元素)
3、可附着对象暂时用一个unity组件实现,具体项目则不一定,这跟实际项目有关。但总之这本质是一个buff的生命周期和触发逻辑管理器。这个管理器决定了元素如何附着如何反应如何残留。
4、CD管理器,在可附着对象中管理自身不同来源对象以及元素的附着和反应CD(工作量关系这部分没做,而且不影响大体效果)

规则要点
反应与附着:遵守先反应后附着的原则,每帧判断——当元素A尝试向某个对象附着时,在A元素中定义了这个元素会按什么顺序去目标对象已附着的元素中寻找能触发反应的元素,如果所有共存中的附着元素都判断过了,且没有反应完毕,则A元素残留的部分会附着在对象上。当附着发生时,触发A元素的附着逻辑。
新旧元素刷新:同款元素新的会刷新旧的,刷新时只触发A元素的刷新逻辑,不触发附着逻辑
DOT元素:如果某个元素是DOT,会在附着期间按指定频率触发DOT逻辑(比如感电就是个隐藏图标的DOT元素,雷水反应的结果只是生成这个元素且0消耗,后面的每次扣元素量+伤害+削韧是感电元素在DOT时做的)
先手后手与克制关系:用一张表或者类似表的数据结构管理反应元素的指向性与消耗比例等参数的关系

已知问题以及一些疑问
只做了4个元素
感电的传导伤害没做
各种反应和附着CD没做
原神中不符合此逻辑框架的特例,不确定是故意这样的还是某种bug——冻结和水共存时,火会先打冻,但即便过量也不会和剩下的水反应,消耗完冻之后火的元素量会被直接清零(注意火是可以和水反应的,但为何会提前结束?);而冻结和冰或水共存时,风会先扩散水或冰,过量的风会继续消耗冻扩散冰(这就又符合先反应后附着的原则了)
疑问1:上述特例在当前框架内可以加补丁实现,但感觉这个设定其实没啥必要?过量火会继续反应水会有什么问题呢?尤其是冻下藏冰时又不会这样,会继续反应掉。所以怀疑是bug
疑问2:附着CD常见的3次或2.5s原则实际本质是削弱高频攻击的伤害增益,频率越高削弱程度越接近2/3
疑问3:扩散水元素的时候不会传递伤害只会传递元素量,这是什么考虑?这么明显的东西一定不是BUG,也一定不是逻辑不好写,肯定是故意的。冰火都可以被扩散出伤害,冰火反应伤害加成也很高啊?这样到底是要限制什么呢?
我的代码欢迎拿去用,或者在评论区提出自己的看法😀

附录-核心代码(详见开头的github链接)






