项目GitHub仓库地址
:
https://github.com/m969/EGamePlay
真是计划赶不上变化,没想到刚写完数值系统不久,就要对数值系统重写升级。 其实之前的那版数值系统在技能效果不是非常复杂的游戏里也是够用的了,可偏偏赶巧不巧就让我遇到了。
效果1
:现在我要实现的一个效果是英雄每损失10%的生命值会提供自身5%的暴击概率。这个效果虽然用之前的数值系统也是可以实现的,但无论我怎么实现都觉得不够简洁优雅。要么就是在效果有变的时候删掉之前的暴击buff加上新的暴击buff,要么就是减掉之前的暴击加成再加上新的暴击加成,这两个我都觉得不够简洁,理想情况下应该是直接用新的暴击加成覆盖掉旧的暴击加成然后刷新一下就行了。
效果2
:如果一个技能效果是屏蔽敌方所有的数值增益效果数秒,不是清除,只是暂时屏蔽,用之前的数值系统实现也是比较别扭。
想要实现直接用新数值覆盖旧数值实现buff刷新的话,我们需要让每一个buff数值变动都单独可控。之前的数值系统都是将数值变动加在一起的,做不到单独可控,所以我们现在需要做一下分离。 我们分离出一个数值修饰器的概念,具体的整形修饰器实现如下:
/// <summary>
/// 整形修饰器
/// </summary>
public
class
IntModifier
{
public
int
Value
;
}
数值修饰器里只有一个字段Value,这个Value保存着单个数值变动的值,+10还是-10。 接着我们再写一个数值修饰器收集器来存储多个数值修饰器: |+10|-3|+6| | ---- | ---- |
/// <summary>
/// 整形修饰器收集器
/// </summary>
public
class
IntModifierCollector
{
public
int
TotalValue
{
get
;
private
set
;
}
private
List
<
IntModifier
>
Modifiers
{
get
;
}
=
new
List
<
IntModifier
>
(
)
;
public
int
AddModifier
(
IntModifier
modifier
)
{
Modifiers
.
Add
(
modifier
)
;
Update
(
)
;
return
TotalValue
;
}
public
int
RemoveModifier
(
IntModifier
modifier
)
{
Modifiers
.
Remove
(
modifier
)
;
Update
(
)
;
return
TotalValue
;
}
public
void
Update
(
)
{
TotalValue
=
0
;
foreach
(
var
item
in
Modifiers
)
{
TotalValue
+=
item
.
Value
;
}
}
}
这个收集器主要有两个接口,一个添加修饰器接口一个移除修饰器接口,每次做添加移除操作后都会刷新一下,计算出TotalValue总累计数值。 最后我们再基于这两个新类来整改我们的数值类:
/// <summary>
/// 整形数值
/// </summary>
public
class
IntNumeric
{
public
int
Value
{
get
;
private
set
;
}
public
int
baseValue
{
get
;
private
set
;
}
public
int
add
{
get
;
private
set
;
}
public
int
pctAdd
{
get
;
private
set
;
}
public
int
finalAdd
{
get
;
private
set
;
}
public
int
finalPctAdd
{
get
;
private
set
;
}
private
IntModifierCollector
AddCollector
{
get
;
}
=
new
IntModifierCollector
(
)
;
private
IntModifierCollector
PctAddCollector
{
get
;
}
=
new
IntModifierCollector
(
)
;
private
IntModifierCollector
FinalAddCollector
{
get
;
}
=
new
IntModifierCollector
(
)
;
private
IntModifierCollector
FinalPctAddCollector
{
get
;
}
=
new
IntModifierCollector
(
)
;
public
void
Initialize
(
)
{
baseValue
=
add
=
pctAdd
=
finalAdd
=
finalPctAdd
=
0
;
}
public
int
SetBase
(
int
value
)
{
baseValue
=
value
;
Update
(
)
;
return
baseValue
;
}
public
void
AddAddModifier
(
IntModifier
modifier
)
{
add
=
AddCollector
.
AddModifier
(
modifier
)
;
Update
(
)
;
}
public
void
AddPctAddModifier
(
IntModifier
modifier
)
{
pctAdd
=
PctAddCollector
.
AddModifier
(
modifier
)
;
Update
(
)
;
}
public
void
AddFinalAddModifier
(
IntModifier
modifier
)
{
finalAdd
=
FinalAddCollector
.
AddModifier
(
modifier
)
;
Update
(
)
;
}
public
void
AddFinalPctAddModifier
(
IntModifier
modifier
)
{
finalPctAdd
=
FinalPctAddCollector
.
AddModifier
(
modifier
)
;
Update
(
)
;
}
public
void
RemoveAddModifier
(
IntModifier
modifier
)
{
add
=
AddCollector
.
RemoveModifier
(
modifier
)
;
Update
(
)
;
}
public
void
RemovePctAddModifier
(
IntModifier
modifier
)
{
pctAdd
=
PctAddCollector
.
RemoveModifier
(
modifier
)
;
Update
(
)
;
}
public
void
RemoveFinalAddModifier
(
IntModifier
modifier
)
{
finalAdd
=
FinalAddCollector
.
RemoveModifier
(
modifier
)
;
Update
(
)
;
}
public
void
RemoveFinalPctAddModifier
(
IntModifier
modifier
)
{
finalPctAdd
=
FinalPctAddCollector
.
RemoveModifier
(
modifier
)
;
Update
(
)
;
}
public
void
Update
(
)
{
var
value1
=
baseValue
;
var
value2
=
(
value1
+
add
)
*
(
100
+
pctAdd
)
/
100f
;
var
value3
=
(
value2
+
finalAdd
)
*
(
100
+
finalPctAdd
)
/
100f
;
Value
=
(
int
)
value3
;
}
}
我们后续还可以在单个修饰器的数值有变动的时候走一下Update流程,这样就可以很简洁的实现前面的效果1了。 我们甚至可以给数值修饰器加一个Enable字段来标记这个数值变动当前是否生效,以此跳过某个数值变动的计算,这样再实现效果2就很方便了。
其实大致的流程没怎么变,主要是细化了其中的每个数值变动的阶段,让其变得更加可控,以应对更加复杂的需求。
最新完整的demo和代码在github仓库可取得。
往期文章:
如何实现一个灵活、通用的战斗(技能)系统——序章
如何实现一个灵活、通用的战斗(技能)系统——数值系统
本文介绍了如何通过设计数值修饰器和收集器,提升游戏数值系统的灵活性,以便于实现英雄生命值减少时暴击概率增加、屏蔽敌方增益效果等复杂技能效果。作者分享了代码示例和GitHub仓库链接,详细展示了从简化系统到应对复杂需求的转变过程。

被折叠的 条评论
为什么被折叠?



