无论您的游戏是否将其数字显示给玩家,很可能它都有依赖它们的底层系统,您可以使用函数来确定这些数字如何相互影响。换句话说,数学函数通常是一系列常见游戏设计问题的核心答案。按住冲刺按钮时,玩家角色的速度如何变化?等等。有时这些问题与明确的数学基础游戏规则有关;有时它们更多地是关于分析和意图,关于你正在构建的电子表格,以后会变成游戏将以其他方式表达的战利品或进度表。这并不意味着作为这些功能的全面入门,更不用说某种分类法了。它更像是一组有趣的样本,以及历史、用例和对其行为的观察。让我们首先通过讨论最简单的函数\(f(x) = bx + a\) 来建立基线。这有助于指出参数化的基础——通过调整\(b\),我们可以改变函数的斜率,使其更陡或更浅;通过调整 \(a\) 我们可以将输出向上或向下移动一定量。使用线性曲线的主要原因是简单明了。玩家可以非常直观地掌握线性系统,这些函数将保持玩家期望的几个属性。例如,如果你加倍 \(x\),那么 \(f(x)\) 也会加倍。如果将 \(x\) 增加某个值 \(y\),那么无论 \(x\) 是多少,\(f(x)\) 都会增加相同的数量。这种清晰度对于试图优化某些东西的玩家来说是无价的。当然,这种简单性排除了更复杂的行为。在很多游戏系统中,玩家不会意识到潜在的数字,而是通过“感觉”来了解系统是如何工作的——在这种情况下,使用易于掌握的线性函数对玩家来说甚至可能不再清晰根本。当然,有时我们不希望游戏系统立即清晰。
幂函数有几个“族”,但首先我们应该讨论 \(f(x) = x^b\),其中 \(b\) 是一些大于 1 的小计数,例如 2、3 或4. 幂函数在\(0 \leq x \leq 1 \) 范围内的“感觉”与在\(x \gt 1\) 范围内的情况大不相同。在单位正方形内,它们“凸出”并远离线性函数,在 0 和 1 点相遇。在那个正方形之外,\(f_{\mathrm{linear}}(x) \lt f_{\mathrm{quadratic}}(x)\),斜率增加到无穷大。如果您期望标准化输入,其中 \(0 \leq x \leq 1\),则幂函数通常用于为动画或角色运动添加“果汁”,作为缓动函数等。 \(x \gt 1\) 在设计系统时更有趣的“外部”范围。力量函数让你加速成长,这对玩家来说感觉很强大,实际上,这本身就很危险。假设玩家角色的伤害和敌人生命值都随着他们的等级呈指数增长;说 \(f_\mathrm{damage}(x_\mathrm{level}) = x_\mathrm{level}^2\)。在实践中,如果玩家与敌人处于同一级别,则游戏会保持相同的平衡,但数字会爆炸性增长。众所周知,当数字大时,玩家会高兴;这对于具有可见损坏数字的游戏来说效果很好。但是,随着玩家等级的提高,每个后续级别的重要性都会有所降低。你可以通过查看 \(\frac{f(x)}{f(x) + 1}\) 的图表来理解为什么:一个 1 级玩家与 2 级敌人战斗可能会造成 25% 的伤害,而级别 10 和级别 11 之间的差异远没有那么显着。当然,如果 x 总是一个更大的整数,这几乎不会那么明显,但它仍然存在。
一切都是相对的,因此增长曲线的“感觉”将取决于它与什么进行比较。为了用功率曲线来说明这一点,请考虑一个 RPG,其中: 随着玩家级别的增加并进入更高级别的内容,任务奖励(金钱)按二次方扩展;消耗品很快变得无限,至少就金钱而言。经过几个级别后,您可以根据需要购买任意数量的药水。相对于任务奖励,装备变得更便宜,尽管高级装备仍然比低级装备更昂贵。如果可以买到超水平的设备,它会变得越来越便宜。如果你失去了一名党员,为他们的复活付出的努力程度总是大致相同的。当然,这些类型的关系来自使用任何函数对任何其他函数。查看游戏不同阶段不同功能之间的比例非常有用,使用这些关系对于实现您拥有的任何玩家体验目标都非常重要。重新考虑 \(f(x) = x^s\),我们显然可以查看 2、3 和 4 以外的指数。使用 \(s\) 的值作为小数进行微调是很常见的曲线并使其完全符合预期。
但是还有另外两个有用的案例。第一个是当 \(s\) 是 0 到 1 之间的某个小数时。这些是收益递减函数,其中变化率随着 \(x\) 的增加而减小,但 \(f(x)\) 永远保持增加.这种功能有很多很多的应用。首先,它前置加载了\(x\)的效果;你可以从少量获得最大的好处,而不是堆积很多。一个很好的用途可能是减少伤害。假设你可以装备一定数量的 \(x\) 件抗寒物品,它们一起可以抵消 \(10x^{0.5}\) 件寒冷伤害。你的第一件抗寒物品可以抵消 10 点伤害。但是要使这种保护加倍并抵消 20 点伤害,您必须将所装备的抗寒物品数量增加四倍。戴上另一副温暖的连指手套、保暖背心或 Ushanka 总是会增加玩家获得的伤害减免量,但拥有一些比拥有很多更重要和引人注目。最后,我们来到负权力。如果您不记得负幂是如何工作的:将某物提升为负幂与取正幂的倒数是一回事;也就是说:后者可能更容易推理,并且计算速度可能更快,如果这对您的应用程序很重要。请注意,对于像 \(f(x) = x^{-s}\) 这样的函数,\(x = 0\) 的值是未定义的,并且接近无穷大。这往往没有用,所以你通常会以 \(f(x) = (x + 1)^{-s}\) 的形式看到它,这将它标准化,使得 \(f(0) = 1\ )。您可以将其视为缓动功能;它随着 \(x\) 的增加而减慢,尽管它永远不会完全稳定。效果非常前置;在上图中,\(x\) 的第一个点将 \(y\) 减半,但随后的点远没有那么有效。但是当我们在 4 时,效果非常微弱。最明显的用例是作为其他东西的乘数来减少它——根据他们的易货技能给予玩家折扣,根据他们的盔甲减少受到的伤害,等等。由于其减速特性,它对于可以叠加的负面效果很有用 - 例如,在玩家累积减益效果时降低玩家的速度。后续的堆叠总是会产生效果,但大部分影响来自第一个。
指数函数\(f(x) = b^x\),其中\(b \gt 1\)。上面显示的是\(e^x - 1\)。与幂函数一样,指数函数增长到无穷大。与幂函数不同,增长率随着价值本身的增长而不断加速,因此每次增长的相对乘数值保持不变。指数增长甚至比二次或三次增长还要大;如果这些函数创建了大的、令玩家满意的数字,那么指数函数很可能会创建更大的数字。在以下情况下使用指数函数可能有意义: 您希望数字真正爆炸。也许您将它们暴露给玩家,而您的游戏就是看到那一大堆零。也许您的游戏涉及范围广泛的音阶。也许输入的范围很小,但您希望这个小范围转化为输出的巨大变化。示例:一个滑稽的物理驱动的高尔夫游戏,其中的笑话是 9 号铁杆比 0 号铁杆射出的球多 \(2^9\) 倍。你想要乘法一致性;也就是增加输入的绝对增幅会增加,但是10级和11级的比例和1级和2级的比例是一样的。你不用担心游戏平衡,要么是因为输入该函数是严格有界的,或者因为您根本不在乎。示例:玩家生命值增长呈指数增长,但基数很小且游戏有等级上限,因此我们知道最小值和最大值是多少。示例:再次,一个闲置游戏,其中的笑话是数字爆炸并且是无限的,直到游戏本身中断。
请记住,虽然指数曲线通常看起来像非常尖锐的“曲棍球棒”曲线,但您可以拥有较浅的指数曲线!只需使用略高于 1 的基数。假设您根据玩家的等级对他们的生命值使用指数缩放,而您的游戏上限为 20 级。您可以定义一个函数,如 \(f(x) = 8 \times 1.25^x\)。这导致数字感觉相对合理——玩家从 1 级开始时有 10 点生命值,在 20 级时将有近 700 点——但在保持相对增长的同时,绝对值仍然迅速增加。指数函数也可以非常直观。上面的 \(8 \times 1.25^x\) 示例本质上是“0 级时 8 点生命值,每级增加 25%”。在某些情况下,这比二次函数更容易让玩家理解。当您将数字直接或间接地通过诸如长度增长的条形之类的东西向玩家展示时,一个有用的感知技巧是使每个绝对增量大于上一个增量,让玩家感觉到力量上升,同时保持他们的相对边际价值。指数函数就是这样做的。与指数增长曲线相近的是指数衰减曲线。这是由如下函数给出的: 感觉与上面的负功率曲线非常相似,但有几个有用的功能。首先,它本质上是标准化的; \(f(0) = 1\),当 \(x\) 接近无穷大时,它总是接近 0。就像“小”指数曲线一样,如果你使用一个漂亮的圆形底座,它也可以本质上被抓住。例如,如果 \(f(x) = \frac{1}{2^x}\),则输出在 \(x\) 的每个单位步长处减半。三角形数非常有趣。想象一下,您将弹珠排列成等边三角形,一边有 \(n\) 个弹珠。你总共需要多少颗弹珠才能完成三角形?
答案总是 n 的三角形数,\(T_n\)。最初,三角形数被定义为整数序列:也就是说,\(n\) 的三角形数只是 1 和 \(n\) 之间所有整数的和。但是这个总和可以概括为一个函数:三角形函数看起来很像幂函数,尽管它是一条微妙不同的曲线。它有一个很好的特性:\(f(x) - f(x-1) = x\)。也就是说,一个步骤和下一个步骤之间的差异与该下一步的函数值相同。这使得三角形数字成为适用于成本和里程碑的非常有用的曲线,例如升级或升级具有连续级别的东西的经验阈值。三角形数字在 Fallen London 中根深蒂固;要在 FL 中增加一个属性,您需要与下一个级别一样多的“更改点”。所以从 4 级到 5 级,你需要 5 个改变点;要从 0 到 5,您总共需要 \(T_5 = 15\) 个变化点。这个直观的属性也用于第 3 版龙与地下城,其中达到 \(x\) 级别所需的 XP 为 \(1000 \times T_{x - 1}\)。因此,您当前级别和下一个级别之间的差异始终是您当前级别的 1000xp 倍。如果系统向玩家公开数字,这比幂函数更容易掌握,同时仍然具有许多相同的属性。
“sigmoid”是任何 S 形曲线。 sigmoid 从某个下限开始,稳步上升,然后在某个上限平稳平稳。有许多具有大致 sigmoid 形状的函数,但我将在这里讨论两个:逻辑函数 \(f_l\) 和代数 sigmoid \(f_s\)。上图:\(f_l\),红色,\(f_s\),蓝色。这两个函数的系数都已调整,因此它们大多会对齐。据我所知,这个 sigmoid 最早是由 James Furness 在游戏设计的上下文中描述的。这是一条归一化曲线;当\(x = 0\) 到\(1\) 时\(x\) 足够大时,它的范围总是从\(0\) 到\(1\)。 \(\sigma\) 和\(\lambda\) 这两个系数分别决定了\(x\) 在曲线达到其下限之前必须有多大,以及曲线上升到该点的陡峭程度。这条曲线有很多优点,包括它本质上是标准化的。它也有一个有用的不对称性,因为它开始快速攀升,但相对较慢。这里有很多系数,但逻辑函数的好处是它们都有非常明确的效果。
\(L\) 是上限,函数收敛到 \(x\) 的高值的数字。 \(k\) 是一个系数,决定曲线上升的陡峭程度;您可以将其设为负数以反转函数的斜率并获得逻辑衰减曲线。 \(e\) 是欧拉数,当然,但就我们的目的而言,它只是一个任意的底数。您可以使用任何大于 \(1\) 的数字,但调整此值与调整 \(k\) 完全等效。 \(x_0\) 是一个简单的加性系数,可以根据需要向左或向右移动曲线。曲线的拐点位于 \(x_0\) 设置的位置——也就是说,上升的中点正好在那个点。除了计算的难易程度不同之外,主要的区别在于它们的偏斜。代数 sigmoid 提前偏斜,前置 \(x\) 的影响;逻辑函数是完全对称的。上图:两个 sigmoid 函数的导数图。它们都是钟形曲线,但代数 sigmoid 的“凸点”明显偏向左侧。首先,它们是归一化函数;他们将接受一个无界输入并吐出一个有界输出。当然,根据您期望的输入值的类型,该输出可能不包含有关原始输入的大量信息。
由于其有界输出,sigmoid 非常适合对某事物的增长实施上限和限制,或者在两个值之间进行平滑。伤害衰减:在 0.5 和 1 之间定义逻辑曲线非常简单,它根据与目标的距离乘以武器造成的伤害。逻辑函数在这里很有用,因为通过调整 \(k\) 和 \(x_0\),不同的武器可以具有不同的射程和或多或少的尖锐衰减曲线。速度奖励:在具有评分和排行榜的游戏中,逻辑曲线可用于根据关卡的标准时间来衡量速度奖励。快速完成关卡的玩家将获得最大的奖励;非常缓慢地完成关卡的玩家将一无所获。在这种情况下,\(x\) 是完成时间,\(k\) 是负数,反转曲线的斜率。 NPC 倾向:您的游戏是一种社交模拟,它的工作原理是将 NPC 倾向修饰符堆叠在一起,例如十字军之王 3。使用 sigmoid 可用于将无界数字规范化为有界值,例如作为输入面部动画系统。再一次,这是一个动物寓言;有限的有趣标本选择。有比这里更多的用例和示例,但我希望这些可以作为人们有用的起点。如果您有问题、想指出错误或对我未包括的内容提出建议,那么提问的最佳地点是通过 tumblr。我不是第一个将这些想法应用到游戏设计中的人,其中很多想法至少在行业的某些子集中是广为人知的。我在这里的大部分想法(以及记录它的愿望)来自与同事的对话,尤其是 Emily Short,她最初向我指出了逻辑曲线。