“与顶尖学者学习”栏目每周都会推送游戏相关的专业课程内容,通过相对专业、系统的知识内容帮助大家提高对游戏的认识和理解。 本文内容来源于清华大学美术学院与腾讯游戏学院联合制作的《游戏编程》系列课程。 课程名称为《游戏玩法开发》(讲师:马若遥)。 文末还有互动学习环节。 欢迎大家踊跃参与,赢取奖励!
#01
游戏开发的定义
玩法开发的定义比较模糊,目前业界还没有完整的定论。 主要是指与玩家交互行为相关的游戏功能和行为的开发。
技术与设计之间的联系
中国游戏团队传统上认为玩法开发是技术与设计的交叉点,这是MMORPG(大型多人在线角色扮演游戏)时代的工作习惯造成的。 在MMORPG时代,玩法是以数值为核心,结合流水线思维开发出来的产品。 由于我国工业化时期较短,艺术娱乐产业经历了时代,游戏开发指的是产业发展过程,从而衍生出流水线思维。
技术与设计的融合
西方团队普遍认为游戏玩法开发是技术和设计的融合,而融合的部分包含更多的技术和设计部分。 最初,由于西方游戏开发团队规模较小,没有游戏设计师的概念。 因此,在FC时代,甚至PS时代,很多游戏团队的设计工作都是由程序员和美工兼职完成的。 基于此,西方游戏团队更喜欢用创作者的思维来开发玩法。 而由于现代独立游戏的兴起,西方很多人对工业化流水线的流程感到反感。
技术、设计与艺术的统一
技术、设计和艺术的统一是游戏开发的终极形式,只有少数顶级开发商才能实现。 这个要求其实并不严格,因为玩法开发团队需要作为核心部分,从确定愿景开始,参与游戏的原创设计和游戏的开发周期,串联起很多制作环节。 比如美术、声音,甚至运营、营销等等,这些环节都是和游戏玩法直接相关的。 因此,玩法开发需要一个真正的多面手来完成。
#02
建立愿景
建立愿景是任何游戏项目开发过程中的第一步也是最重要的一步。 无论您是与单个开发人员一起开发简单的小型独立游戏,还是与数百或数千人一起开发大型项目,第一步都是要有愿景。
愿景定义
视觉是描述游戏最核心也是最重要的部分。 清晰的愿景是项目成功的保证,但问题是愿景本身可能是模糊的。 因此,往往需要通过迭代和项目进度来解决愿景模糊的问题。 随着项目的进展,愿景可能会发生变化。
许多项目都会有一个负责人作为愿景持有者。 比如著名的游戏制作人小岛秀夫,比如顽皮狗工作室的《最后生还者》,就有比较明确的制作人; 但也有很多游戏的制作者并不清楚。 例如,使命召唤。
一个游戏项目是否有一个人作为明确的Vision Holder,其实并不那么重要。 因为愿景是否清晰的标准在于执行者是否清晰。
另一方面,并不是只有创意总监才能思考愿景,愿景也不仅仅存在于大型游戏项目中。 我们对小事物也有愿景,例如子系统。
如何传达您的愿景
有很多方法可以传达您的愿景,而不仅仅是项目文件。 很多时候,国内团队喜欢用Excel、Word、网页或者冗长的设计文档来传达设计愿景,但如果执行者不阅读或不理解文档,那是没有意义的。
无论如何,评估设计愿景的标准仍然是:执行者是否清晰。 因此,最重要的是,愿景存在于执行者的头脑中。 我们应该使用一切行动、写作、绘画和使用例子的方式来尽可能清晰地传达我们的愿景。
愿景沟通后,沟通者和执行者需要共同努力,达成结论和共识。 执行者可以通过结论和共识最终执行这个过程,所以结论和共识也是游戏中看到的最终状态。 但落实到实际工作中,就会出现不同的情况和变化。
三消视野
让我们用三消游戏的例子来解释如何建立愿景。
在制作三消游戏之前,首先尝试建立一个愿景。 按照标准的三消游戏,一般玩法是这样的:当砖块掉落时,玩家可以交换砖块的位置,三块相同颜色的砖块连在一起就会消失。
但清晰地传达愿景并不容易。 仅通过描述玩法和具体流程图可能并不清楚愿景是什么。 例如,如果你从未玩过三消游戏,当你看到玩法描述和流程图时,你只能想到俄罗斯方块游戏。
我们参考现有的三消游戏来描述一下,这样可能会让三消游戏的愿景更加清晰。 例如:
①首先说明这是一块N×M大小的板,上面铺有砖块;
②然后定义Match 3和Match。 当三块或更多相同颜色的砖块连成一条线时,称为匹配。 组成匹配的砖块将被消除并增加分数;
③最后说明玩家的操作可以交换相邻两块砖块的位置,从而形成匹配。 消除后的空位会被上方自动落下的砖块填满。
通过另一个游戏的例子可以使愿景更加清晰。 但愿景一旦明确,仍然只有一个轮廓,具体细节还不清楚。
因此,下一步就是采用分而治之的策略。 分治策略是游戏开发中的重要思维方式。 例如,编程中许多算法的实现都使用了这种策略。
分而治之的策略
分而治之策略(Divide and Conquer),简单来说,就是将一项大任务分解为若干个小任务,并逐一攻克。 对于愿景来说,分而治之就是根据个人或团队的工作习惯,将其拆分成易于实现的模块。
分治策略也可以用来分析成品游戏,比如大家熟悉的游戏《超级马里奥》:
根据上图,我们采用分而治之的策略,大概可以分离出关卡、地形、主角、敌人、水管、金币、分数等元素。如果我们要做这个游戏,当使用拆分方法与团队其他成员讨论时,我们可能会遇到一些问题:例如
①得分应该奖励给主角还是敌人?
②水管只是水管,还是被认为是水平或地形的一部分?
③关于火球和飞锤,制作飞行物的程序员会认为它们属于同一类别,在制作飞行物系统时都使用。 但也有人可能认为漂浮在空中的金币也被认为是飞行物。
事实上,这些问题并没有绝对的答案。 新团队可能会发生争吵,但没必要纠缠这些。 现阶段最重要的是推动这一进程。
三消拆解
仍然以三消游戏为例来拆解三消游戏,它的元素大致分为:世界、棋盘、砖块、记分牌、菜单。
世界是整个游戏的容器,包括关卡、道具、玩家图像等; 棋盘是每一层静态元素的总和; 砖块是落在屏幕上并被玩家拖动的东西,即屏幕中的动态元素。
但这样拆解之后,就会出现一些问题和矛盾:比如
① 砖块将占据一格。 如果砖块都被消除了,剩下的格子是多少? 它可以被视为董事会的一部分吗?
② 如果游戏没有关卡而只有一个关卡,棋盘和世界是在一起还是独立?
③如果游戏有胜利规则,那么如何定义游戏的胜利? 是淘汰到一定分数的时候还是时间归零的时候? 胜利的规则是由世界还是棋盘决定的?
这些问题可以暂时搁置。 我们先介绍一个简单的原理:KISS。
KISS(保持简单和愚蠢)
KISS 代表保持简单和愚蠢。 当有A、B、C三个选项可供选择,而我们又不确定A、B、C哪个选项好时,我们可以选择最简单的选项,先做最好的选项。
虽然有人认为这种做法过于无计划,但不确定性是游戏项目中非常突出的特征,尤其是在玩法开发中。 游戏开发并不是纯粹的技术工作。 当不确定性出现时,团队可能会争论,甚至产生恐惧感。 争论和恐惧会影响团队决策,从而导致项目无法推进并按时完成,最终可能导致游戏无法发布。 很多时候,我们不知道外部环境会如何变化,也不知道现在做出的关于未来思考的决定在未来是否行得通,所以我们不妨运用这个原则:Keep It Simple and Stupid 。
除了KISS之外,业界流行的概念还有:
① YAGNI-You ain't gone need it(避免诱导但不发出),主要指我们为未来做的一些准备。 如果我们现在不使用它,将来可能也不需要它。 因此,基于“不触发,避免触发”的原则,我们不需要提前准备太多,等到必要时即可。
② If it ain't bad don't fix it(不要提前计划),主要是指当你正在做的内容有缺陷时,你不需要急于解决它,你会当问题出现时解决它。
利用KISS原理来简化拆解的三消元素。 例如,如果董事会不确定,可以将其放在世界第一,而无需单独列出; 如果砖块占用的格子不确定,也可以放在世界第一。 只剩下世界和砖块了。
世界都是静态元素,而砖块都是动态元素。 至此,许多不确定因素已经解决,项目范围也将变得清晰。
#03
划定界限
对于一个项目来说,Scope(边界)是非常重要的一部分,因为Scope决定了我们需要的资源,包括时间、金钱等。
无论是一个人制作的独立游戏,还是千人制作的大型游戏,都需要确定Scope。 范围和愿景是最重要的两件事。
接下来,您可以开始实际编写代码。 这里显示的代码是简单的伪代码而不是实际代码。
上图是Brick类和World类的伪代码。
左侧的代码按颜色定义了砖块的类别。 这里我们就犯了“挑衅而不发动”的错误。 我们假设未来会有合成炸弹的机制,但整个三消游戏完成后,并没有使用它。
世界级也比较简单。 我们可以先用一个贴图将其映射到实际图像上,然后定义世界的大小,比如10×10,最后编写一个相机来定义分辨率。
在这里,我想介绍一下我的个人经验,那就是快速屏幕启动的原则:工作量越少,屏幕上能看到早期的原型,项目进展就越顺利。 因为当我们看到具体的内容之后,我们就可以开始和别人讨论,有目的地改进,而不是纸上谈兵。 代码本身只是一种文档。 编译后,无论是变成机器码还是任何形式,只有运行起来才能达到我们想要的结果。
#04
迭代
迭代的核心思想是快速试错,当面临设计不确定性时我们应该拥抱它。 这也和上面的KISS原理是一致的。
因为在游戏项目上线之前,游戏设计会遇到很多不确定因素。 设计的不确定性本质上是由于现有信息不足以支持决策。 “想了就不改”的状态是很难达到的。 市场总是在变化,玩家总是在变化,项目的状态也会不断变化。
迭代循环
从设计开始,到实现、体验、反馈,最后到设计形成一个循环,就是一个迭代; 多次重复这个过程就是一个迭代循环。
如果想要快速试错,就需要降低每个周期的成本。 随着时间的推移,迭代本质上是一种分而治之的策略。 每当你完成一个阶段时,你需要反复问自己:下一步是什么? 目的是促进项目快速进展,顺利完成项目。
面向对象
面向对象是一种封装数据和逻辑的编程思想范式。
比如皮卡丘对应的类型是皮卡丘,它有等级、生命值、攻击、闪避、进化等属性,相关的代码封装在一起形成一个类,这个类就是一个对象。 集中管理相关代码的目的是为了方便维护和复用。 许多现代商用发动机都是这种情况。 在Unity和Unreal中,有Actors、GameObjects等,它将图像、模型、声音等所有元素放在一起,并将代码放在里面。 这是一个物体。
对象可以被继承。 如果皮卡丘进化成雷丘,雷丘的攻击等行为可以直接继承皮卡丘的属性。
但面向对象并不是唯一的范例。 比如《使命召唤》的引擎就不是C++,而是纯C语言。 C语言不是面向对象的语言,它的编辑器也不是面向对象的。
以上表为例。 如果不从程序的角度来看,它就不是面向对象的范例。 游戏策划者可能不关心每个对象包含的内容; 他关心的是每个对象中的几类重要的内容以及它们之间的关系。
因此,设计不一定必须是面向对象的。 很多时候,面向对象不一定是最好的解决方案。 我们必须在正确的地方使用正确的工具。
砖块是一个相对自然、可复制的个体,我们关注它的价值。 所以我们首先将砖块写成一个对象。 如上图所示,代码的上半部分是砖块的属性,下半部分是砖块的起点、终点和移动方向。 砖块的移动需要使用插值函数来完成。
插值法
插值相关术语包括:Lerp(Linear Interpolation,线性插值)、Interp、MapRange、Bezier/Hermite curve(贝塞尔/埃尔米特曲线)等。
插值,简单来说就是一条直线或曲线。 当X改变时,Y也随之改变。 它是非常基础的内容,但应用范围很广,可以解决日常工作中的大部分“过渡”问题。 屏幕上的许多很酷的动画都可以使用插值来完成。 如上例,艺术家只制作了几个关键帧,中间过程通过插值完成。 无论是30帧、60帧还是90帧,都可以看起来流畅。 这实际上是一个分而治之的概念。
玩家输入
关于砖块的交换行为,有两种设计思路:第一种是玩家点击选择砖块,然后选择相邻的砖块来交换两者;第一种是玩家点击选择砖块,然后选择相邻的砖块来交换两者; 第二种是玩家向某个方向拖动砖块,砖块与该方向上相邻的砖块交换位置。
第一种设计更容易实现,但将复杂性留给了玩家。 如果在手机上玩这款游戏,玩家可能会遇到误点击、漏点击、滑点的问题。
第二种设计比较复杂,因为玩家的手势判断很难确定。 这时候我们可以做一个折衷的方案,在方案二的基础上进行简化,不再执行标准的拖动动作,而是使用MouseDown和MouseUp,并明确界限:一共有四个方向。 只考虑从按下到抬起的点,以及该点属于哪个区间。在该区间内,砖块与相邻的砖块交换位置。 这个折衷方案并不比第一个复杂多少,只是需要多一点数学计算,但它大致实现了第二种想法。 这是KISS原则的一个体现。
砖块破坏
最后,我们要做的就是砖块的诞生和毁灭。 要实现破坏,只需删除并添加简单的特效即可。 在实际代码中,需要处理一些引用关系。 例如,某块砖被删除,就会留下空位,某块砖有参考点,需要与其交换另一块砖。 这些情况都需要进行处理。
假设我们做了一个很好的删除播放特效,但前提是砖块需要匹配3次,并且必须收集到3个才能触发。 此时我们暂时不需要处理,可以先写一些临时的测试逻辑。 三消游戏的情况比较简单,可能不需要写测试逻辑,但也会有其他更复杂的情况。
例如,《绝地求生》游戏中,有一辆可以在山坡上行驶的摩托车。 当我们制造出摩托车后,我们会与团队进行沟通。 我们可能会发现摩托车已经准备好了,但玩家部分还没有准备好。 这个时候虽然工作量巨大,但一般情况下,我们还需要再写一个复杂的逻辑,让玩家一进入关卡就可以驾驶摩托车。 经常被验证,这也是一个分而治之的概念。 它可以防止我们在上线或验收之前将所有内容放在一起进行验收,以防在所有内容一起验证时出现问题。
落下的砖块
消除砖块后,相邻的砖块就会掉落。 处理掉落的砖块有两种方法:
空地上所有的砖块一起落下,砖块一块一块地落下。 处理普通跌倒的方法有点复杂。 我们可以让砖块一块一块落下,以填补空缺。 优点是可以应用砖块的交换逻辑,不需要写复杂的掉落逻辑。 只需交换上下砖块或调整数值即可。 坠落效果还是不错的。 但其中可能存在很多Bug。 例如,一块黄砖落在它下面的格子上,如果它掉落的相邻两个格子都是黄砖,那么整个屏幕仍然会处于下落的过程中。 当没有稳定性时,直接淘汰。 因为淘汰的逻辑是每次掉落后检查三消,每次掉落后检查一次,所以这个时候就会出现bug。
生成新砖块
如果有一个空格子,上面的砖块就会掉落,然后顶部会生成新的砖块并一起掉落。 把顶部新砖的生成和根据空位的数量落下砖看作一个问题太复杂了。 我们可以将其简化为一块一块地生成砖块。 这种处理方式也可以解决首屏的问题。
第一屏问题是指一开始屏幕上生成所有砖块后,可能会出现三块相连的相同颜色的砖块。 然而,MatchThree 程序仅在砖块掉落时检测它们,因此现有程序无法消除这三块砖块。 但是我们可以通过让砖块成行生成来解决这个问题,等到最上面一行生成后再落下,然后再生成另一行砖块。
检测三消
三消检测是触发砖块破坏的过程。 这个过程仅在砖块移动后发生。 其实也是算法的一种优化。 该算法的运行成本比较昂贵。 如果有10000块砖,并且只能一一检测,检测算法可能需要运行数千万次。 这种情况在实际游戏中经常遇到,所以我们需要想办法去优化。 优化也是一种分治策略,包括时间分治和空间分治。
优化检测属于时间分而治之。 如果在特定事件发生后才进行操作,就不需要每一帧每一帧都检测,及时检测到的概率会小很多。
但是我们的三消检测仍然存在一个错误:如果一块砖块掉落,其右侧相邻的格子颜色不同,但左侧的两个相邻格子颜色相同。 在这种情况下,不会发生消除。 由于该算法只检测落砖的上、下、左、右方向,因此需要检测多次。
测试与调试
简单的测试代码有很多用途。
首先,在功能完全实现之前可以消除一些错误。 这避免了所有错误都集中在一起。
其次,我们可以有意修改一些代码来帮助重现该错误。 因为有些bug比较特殊,只有在外部条件非常复杂的情况下才会出现,但其出现的概率却不够小。 它可能是万分之一而不是百万分之一。 当游戏有上百万玩家的时候,很多玩家都会遇到这个bug。 这个时候我们就需要进行测试。 有了足够的信息,知道了bug所依赖的逻辑线,我们就可以进行修改,使程序只遵循这条逻辑线,从而有助于测试代码。
另外,还有一种更极端的方式,就是有些游戏的客户端和服务器是分离的。 客户端负责渲染,服务器向客户端发送合约,指导客户端进行操作。 如果客户端的逻辑是确定性的,即每次执行相同的输入时都会执行相同的输出。 在这样的条件下,就可以记录外部环境。 比如某些游戏中的录音功能是可以回放的。 如果播放过程中渲染过程出现Bug,可以使用更先进的开发工具来快速调试。
最后,有时测试甚至可以帮助迭代,加快迭代速度。
虽然Log(屏幕消息)被认为是原始社会的产物,但它有很多好处。 它和调试器是两个共存的元素。
调试器的优点是善于跟踪更深层次的逻辑树。 例如,如果在某个点看到错误,则实际逻辑可能不一定发生在该点。 之前或之后的一些数据可能有问题。 这个时候我们再利用Log(屏幕消息)来调试就会非常困难。 我们需要添加大量内容才能看到一些有问题的数据。 而且,在使用Log的过程中,会出现打字太多而找不到的情况。 关键点都达到了,但是调试器可以很好的找到问题数据。
但Log也有自己的优点。 它可以清楚地看到错误。 在大型团队中,非编程技术人员可以随时打开和关闭登录,以在屏幕上显示错误。 他们可以直接将屏幕截图发送给程序负责人,而无需使用编辑器。 人员调试简单快捷。 另外,很多游戏发布后,Log可能是唯一有效的执行手段。 如果用户崩溃了,我们能得到的只是一个Log。
辅助图形(Debug Draw)就是在屏幕上绘制一些帧,与Log类似。 如果遇到Bug,直接截图并将相关的Debug Draw发送给技术人员,以便技术人员可以直接定位问题出现在哪里。
Debug Draw 也可以辅助开发。 例如,敌方AI的构成很复杂,可能是机器人、僵尸、动物和人类的组合。 它的行为也比较复杂,可以使用十八种武器。 这时,敌方AI做出了动作。 创意总监认为这个动作不应该在这个时间点做出,所以程序员需要找到原因。 这时候,如果我们把AI各个系统中的参数、评价函数的结果等画出来,输出到AI的头顶上方,我们或许就能明白动作的原因。
Assert就是在写函数的时候预先写出预设值。 例如,该值应介于 0 和 1 之间,或者该值不应为负数。 写入程序的时候,如果程序崩溃了,出了问题,就会报错,然后就可以明确错误的问题了。
但程序崩溃也会引发新的问题。 例如,您正在处理的编辑器希望设计者在文本框中填写0到1之间的数字。 写完断言后,设计者填写数字2后,编辑器直接崩溃。如果你在游戏逻辑中写了断言,别人修改了,游戏就会直接崩溃,最终你会发现断言没有效果。 在这种情况下,常见的处理方法是自己编写一个断言库。 当断言发生时,它只是调出调用堆栈,编辑器不会崩溃。
#05
波兰语波兰语
游戏设计的最后一步是打磨。 打磨是将游戏从功能性转变为艺术性的过程。
游戏设计有一个MDA模型,它指的是Mechanics、Dynamics和Aesthetics。 例如,如果角色在按下按钮后移动,则称为力学; 如果角色着火了,并且他周围的树木在行走时也着火了,那么不同系统之间点燃的交互称为动力学; 美学是从玩家的角度来描述的。 比如我们刚才谈到了玩家的移动和火力。 其实从发展的角度来看,只是玩家向树木传递了某种属性和特效,而火/水的概念就是美学的概念。
#06
开发者视角和玩家视角
从开发者的角度来看,MDA是基于功能的,其次是系统之间的动态交互,最后是美观方面。
从玩家的角度来看,首先遇到的是审美层面,然后才了解动态和功能。 有些玩家甚至不了解这些功能。
因此,玩家和游戏开发商看到的品质是不同的。 玩家会非常关心小值不平衡、错误、滞后和崩溃等质量问题。 比如游戏《刺客信条:团结》就完全还原了巴黎圣母院。 但刚发售的时候,玩家们都会因为头发系统、脸部系统等问题,因为这些小bug而给游戏评分很低。 但是这些错误对开发人员可能并不严重,只是显示错误。
抛光解决了这个问题。 最重要的一点是开发人员需要留出足够的时间。 因为完成功能后,整个游戏实际上都没有完成。 仍然需要创建游戏的艺术效果。
奖励学习!
我们将在2021年9月13日17:00吸引2名幸运的学生,并分别赠送Upup ox ox ox ox series系列时尚玩具人物集。 参与方式如下:
①文章末尾的右下角的“阅读”单击
评论列表