资讯
展览资讯 大型展会 灯光节 大型盛典 赛事 中标捷报 产品快讯 热门话题 艺术节 活动 演出 新闻 数艺报道 俱乐部签约
观点
大咖专访 观点洞察 书籍推荐 吐槽 设计观点 企业访谈 问答 趋势创新 论文 职场方法 薪资报价 数艺专访
幕后
幕后故事 团队访谈 经验分享 解密 评测 数艺访谈
干货
设计方案 策划方案 素材资源 教程 文案资源 PPT下载 入门宝典 作品合集 产品手册 电子书 项目对接
  • 0
  • 0
  • 0

分享

如何让玩家爱不释手,在游戏设计中加点儿“意外”

原创 2022-06-20

游戏需要制定明确的机制,只有这样才能让玩家知道该如何一步步升级;同时,游戏也需要“意外”,如果玩家在游戏里的行为结果太过有迹可循,很容易让玩家失去兴趣。


在本文中,资深技术游戏设计师 Christo Nobbs 将以例子深入说明怎样给游戏添加随机元素,从而让玩家保持兴趣和期待


如果你想要掌握更多关于游戏设计的技巧,欢迎学习我们新推出的免费教程《Unity 游戏设计师实操手册》,该教程由 Christo Nobbs 参与编写。
https://learn.u3d.cn/tutorial/unity-game-designer-playbook



为玩家留下充足的视觉线索


用户可以借助显眼的图像元素来吸引玩家进一步探索游戏系统,催生独特的游戏体验。上一篇文章中(点击回看),着重介绍了一个由大量树木组成的沙盒世界,这些木头在特定条件下可能会着火并让火势蔓延。游戏设计师在此基础上再给玩家一把斧子,让玩家可以砍树。


假设玩家所在之处完全平整,那他们将难以预测树倒下的方向。如果有些树是那种已经“死了”但还矗立着的枯树呢?这些枯树说不定什么时候就会倒下。这种不确定元素可以为游戏体验带来刺激和紧张感。 


你可以用画面来告诉玩家这些倒下的树十分危险,让他们保持警觉。玩家则能通过图像细节来分辨危险的枯木和健康的普通树木,然后自行权衡利弊。没准儿玩家会因此思考:如果直接在已经倒地的树上收集柴火,从而避免被危险的枯木伤到,这样会不会更明智点?


作为一名游戏设计师,我们一定要罗列出这些可能的连锁反应,再围绕着它设计,保证它能顺利发生,比如树木向随机的方向倒下、甚至偶尔着火,这些元素都可以引发混乱但有趣的状况。


善用Unity.Engine.Random来产生惊喜


Unity 的 Random 脚本类是一种生成随机数据的静态类。它与 .NET 框架下的 System.Random 有着同样的名称与相似的功能,但两者之间有着几种关键的不同——比如前者要比后者快 20%-40%。


Random 脚本类:
https://docs.unity.cn/cn/current/ScriptReference/Random.html


Random 类所包含的静态属性和方法如下:


静态属性:
 insideUnitCircle:返回圆半径1.0以内或边缘上的某一点(只读)
 insideUnitSphere:返回球半径1.0以内或边缘上的某一点(只读)
 onUnitSphere:返回球半径为1.0的球面上的某一点(只读)
 Rotation:返回一个随机旋转角(只读)
 rotationUniform:返回一个均匀分布的随机旋转角(只读)
 state:取得或设定随机数字生成器的内部状态

 value:返回一个(包括)0.0到1.0之间的随机浮点数(只读)


静态方法:
 ColorHSV:从HSV和alpha数值范围中生成一种随机色彩
 InitState:以一串种子值初始化随机数字生成器
 Range:返回一个(包括)[minInclusive..maxInclusive]之间的随机浮点数


我们在上一篇博文里探讨了“操纵杆”(调试键)的作用,以及如何使用 ScriptableObjects 来储存调试数值。你可以用 Unity 的 Random.Range 设定一个数值范围,用随机生成的浮点数来取代固定的调试数值。此时,包括最大最小值在内的任意浮点数会在每 1 千万个随机样本中出现一次。


你可以使用这种方法从数值范围中抽取出一个用于游戏的值。只要多实验几次,你就能找到最适合游戏的范围,然后再围绕着这个范围进行设计。


请在我们第一期游戏设计博文中详细了解什么是模块化系统

随机化的森林冒险


随机元素能让游戏更吸引人。


打个比方,假设树有着 100 点的固定血量,而玩家每次挥砍斧子可造成 25 点伤害。那砍树这件事很快会变得可预测且无聊。即便树木的血量在 76 到 100 点间浮动,每棵树仍是砍四下就倒。不过若血量设在了 75 到 76 之间,则游戏玩法会非常不同,这时每棵树需要被砍三到四下才会倒。


另一种给砍树添加趣味的方法是隐藏血条,用视觉线索来暗示血量变化。这样一来,玩家将从游戏过程中逐渐学习到砍倒一棵树要多久。视觉线索可以增添有限的不确定性,这些不确定性可根据游戏玩法进行平衡和调整。而放弃固定数值、善用 Random 类可让原本单调的任务变成一种有趣的体验。


要想更进一步,你可以让每次挥砍减少 15 到 25 点的伤害。这样一来玩家将很难准确判断砍倒一棵树要多久。他们只得依靠视觉线索来揣测这棵树何时会被砍倒;这些线索可以是砍飞的碎块大小、树桩的切口大小、掉落的树枝多少、树干断裂的音效等等。


玩家不能准确预测树木倒下的时机,但砍得越多,玩家就能猜得越准,并最终提高自己的生存几率。


随机化的Damage Intensity(伤害强度)数值将影响最终的Damage Value(伤害值)——该字段使用了Range特性显示了出来。


随机的目的是给玩家带来意料之外的挑战,促使他们权衡风险、争取最好的结果。


接下来我们再来看看几个使用 Random 类的例子。


卡牌游戏中的随机


假设某款卡牌游戏里的 AI 对手只会针对玩家的操作而出牌。如果没有随机性,对手每次出牌都会是固定的,因而也变得容易预测。即便变成了二选一,这样的随机还是太简单,玩家会很快总结出一套规律。


因此,我们可以试着在 AI 的每一步反击上增添一层随机性。如此一来,AI 不会仅仅只从卡池里选两张牌之一打出,或一直优先打出某张牌而放弃其他牌,让整个系统更加复杂、游戏更具动态。


你可以设定几种难度,让不同难度下的对手优先出特定几张牌;比方说,根据预设的值或攻击前的手牌来预测出需要出的牌。如果有一张王牌和其他强力卡牌搭配时可以造成数倍伤害,那对手就可以等到手牌中凑齐了这些卡牌后再打出,给玩家增加难度。你可以通过提高或减少某张王牌与其他强力卡牌一起打出的可能性,来给这种出牌组合设置“权重”。


由暴雪娱乐开发的《炉石传说》仍是当今最受欢迎的卡牌游戏之一。这款于2014年上线的游戏正是用Unity开发的。

柏林噪声(Perlin noise)


随机性能以不同的形式出现在游戏中。比如,柏林噪声(Perlin noise)就能根据一串种子值来生成自然的递进噪声,它可以在 Cinemachine中产生更加自然的第三人称跟随镜头。


Perlin noise算法可以让Cinemachine的镜头移动更加生动


要想尝试 Perlin noise,可以在资源商店上打开 Starter Assets - Third-person Character Controller 或 Gaia 资源包,或参考 Mathf.PerlinNoise 文档。


Mathf.PerlinNoise 文档:
https://docs.unity.cn/cn/current/ScriptReference/Mathf.PerlinNoise.html


根据Perlin noise算法采样而来的纹理。柏林噪声并非完全随机的数值,而是按照一定的模式逐渐增加或降低、形成一个个“波浪”。这种噪声可用于纹理效果和动画的制作、地形高度图的生成等等。

攻击AI代理


在一次采访中,《光环2》的首席工程师 Chris Butcher 在讨论游戏的 AI 时表示:“我们的目标并不是创造出那种不可预测的东西。这里的人工智能必须有高度的连贯性,可以识别特定的玩家输入。让玩家在做出某些动作后可以预测到 AI 的反应。“


这些资产包含在资源商店的Starter Assets - Third-person Character Controller资源包中


在这个前提下,我们该怎样建立 AI 代理同时保持游戏的不确定性和活力呢?


一种方法是用资源商店的 Starter Assets 和 AI 工具进行实验,比如能让 AI 代理向某个位置移动的 A* Pathfinding Project Pro。


Starter Assets:
https://assetstore.unity.com/packages/essentials/starter-assets-third-person-character-controller-196526#description


A* Pathfinding Project Pro:
https://assetstore.unity.com/packages/tools/ai/a-pathfinding-project-pro-87744


当 AI 代理走向玩家时,玩家觉得自己马上会遭到攻击。但如果它走过来只是为了对话呢?如果我们想要加入更多四处走动、融入环境的 NPC,让周围的环境更有活力呢?这些 NPC 应该线性地收到可以前往的地点,或者根据一套规则并用 Random 类来选取符合逻辑的地点。


假设有一个 AI 代理能用一张较弱的弓向玩家射箭。不幸的是,代理必须站在一定的距离内才能射击,因为它的最大射程是十米。当 AI 站到了玩家面前 10 米处时,便会开火。这样的安排算不上理想,尤其是有第二个弓箭手也想在 NavMesh 上争夺同一个位置时。


要让这个情景更为有趣,我们可以划定一块区域让敌人来靠近玩家。我们能用 Random.insideUnitCircle 实现这点,将输出的 vector2 传入到 vector3 空间坐标的 X 和 Z 轴上,然后利用 RandomRange 在玩家周围划出一块最小与最大值之间的圆。


AI代理选取攻击位置的脚本


“调试杆”这时就能用于在检视器中微调AI行为了


AI 代理应该在玩家附近选取一个位置再射击,而不是过于靠近玩家。为了用最少的代码带来更多的刺激,所有 AI 代理都能应用这个脚本,并从多个角度攻击玩家。AI 的行为在一定程度上是可以预判的,代理会在一个固定的距离展开攻击,但你并不能预测攻击的角度。


红点代表了代理将前往的位置


你也可以在此基础上为代理添加近战攻击的能力。用同样的方法在玩家的近身距离内随机取得地点,让代理能在适当的时机选择自己的攻击方式。


玩家知道自己有可能会遭受近战攻击,但从哪个方向来呢?会不会有举过头顶的高位攻击?或者从左到右的横扫攻击?玩家只能通过观察动画上的文字来确定即将来临的攻击。



这时如果有多个敌对 NPC 意图攻击玩家,则整个状况会立即变得复杂。不过在育碧的《Far Cry 2》里,玩家并不会同时遭受所有敌人的进攻。不同的敌人有着各自的攻击时机与方式。


如果你希望在游戏中真实地还原现实动作所产生的结果,你就必须应用复杂、多方面的等式或一个训练好的 ML 代理。最终,这种效果很可能仍然无法契合游戏,并且实行的耗时长、技术要求高,且如果架构得差,要理解、平衡或控制起来会非常困难。


不过在 Unity Random 类的帮助下,游戏设计师们也可以为场景创造逼真的效果、控制游戏的刺激程度,相比于其他方法,这样也能节省不少时间。当然,随机性不一定处处适用,确定性仍然十分重要。但只要在合适的地方、合适的时机善加利用,你就能给玩家带去非常独特的游戏体验,吸引玩家一次又一次地进入游戏。




长按关注

Unity 官方微信

第一时间了解Unity引擎动向,学习最新开发技巧


阅读原文

* 文章为作者独立观点,不代表数艺网立场转载须知

本文内容由数艺网收录采集自微信公众号Unity官方平台 ,并经数艺网进行了排版优化。转载此文章请在文章开头和结尾标注“作者”、“来源:数艺网” 并附上本页链接: 如您不希望被数艺网所收录,感觉到侵犯到了您的权益,请及时告知数艺网,我们表示诚挚的歉意,并及时处理或删除。

数字媒体艺术 游戏设计 游戏设计师

15229 举报
  0
登录| 注册 后参与评论