灵活运用Unity的典范。
分享/丁成甲 整理/依光流
11月18日晚,在Unity线上技术大会游戏专场,《帕斯卡契约》的总导演兼美术总监丁成甲分享了他们的制作流程和思路。这款游戏是少有的单机手游,而且在前不久,它的销量超过了100万,实属难得。
《帕斯卡契约》身上有诸多的特殊性,它在手机平台做出了主机游戏的观感,甚至因此登上了苹果发布会,成为经典案例。但实际上它并没有硬堆品质,而是采用了很多取巧的方式,规避了过度的资源消耗。
从最开始,其研发团队Tipsworks只有10个人,到现在也维持在30人左右。这次分享最有意思的地方莫过于:在团队人手有限的情况下,如何发挥自己的长板规避短板,找准制作的思路,从而在移动端实现一个足够亮眼的效果。
以下为丁成甲的分享,游戏葡萄整理:
大家好,我是《帕斯卡契约》的总导演兼美术总监,负责项目里的剧情框架、游戏玩法还有美术表现。本期我会以游戏制作的角度来介绍一下《帕斯卡契约》的创作流程,展示一下在创作《帕斯卡契约》中,我们经历了哪些阶段?最后我会举一些游戏中的例子来解析一下美术表现与优化。
首先介绍一下我们的项目,《帕斯卡契约》是使用unity来制作的一款动作角色扮演项目,最开始我们用的是unity的5.6版本,后来到研发的最后一年我们升级到unity 2018。我们从2016年开始研发,大概消耗了三年的研发周期,制作人员在第一年大概有10个人,一点一点扩大,到最后一年我们大概有30个人,整个项目95%的资源都是自己产出的。
这就是我们公司的一面墙,早期的时候我们会在墙上面去做很多的尝试,其实我们早期也没有太多的方向,当时做了非常多的风格尝试。
接着我在地方出了一个这样的小稿,这是一组黑暗中世纪题材的概念图。出了稿子以后,当时工作室里的每一个人看了稿子以后都觉得非常有兴趣,大家出乎意料的一致,觉得方向可以试一试。
确定了目标以后,我又继续做了一些人设的细化,那就有了现在这张图是有剑士,有女巫,有贵族,猎魔人,重甲骑士等风格。
但是因为我们当时就10个人左右的人力,决定还是把体量控制的小一点,我们商量了一下,觉得做一款中世纪题材的动作对战游戏,可能是一个比较保险的方案。
然后就到了我们项目开始定初期目标,这阶段我们觉得定的目标始终要量力而为,定一个可实际完成的体量,定一个可实现的玩法,而不是说我脑子里有非常多、非常赞的点子,但是实际制作的时候处处碰壁,结果你只能完成它的60%或者70%。所以我们考虑了很多,希望把制作体量控制在一个可掌控的范围之内,这是我们当时做的一个初期的联机对战demo。
当时10个人花了一年,做了一个已经可以刷到手机上的联机对战模式,可以WiFi联机,就像《荣耀战魂》一样的PVP,但是当时确实游戏性和画面都没有调的很好,游戏内容略微有点单薄,所以我们决定加入一些PVE元素。
这是接下来为 PVE模式出的一张场景设定,一个看起来有点诡异而破败的村庄。为此我们开始思考游戏的世界观和简单的一些故事。
当时我们做了一个所谓基地的PVE玩法,怪物不断从远方涌过来,玩家保护基地,需要不断的击杀怪物获得能量,然后用能量强化自身,不断的迎接下一波怪物。
这个PVE玩法现在看起来非常简单,但是对于当时来说,对我们来说确实意义非常重大,因为时候我们终于得到了一个像样的游戏框架,而且玩起来确实也蛮有趣,那给了我们前期非常大的信心,我们看到这一步了以后想想还不如把这块好好做一做。
有幸的是场景最后被保存了下来。这个场景现在是我们最终上线了以后,第一关海格姆的画面,基本保留了原来那块区域,然后在这个基础上又继续扩展了场景,这个时候我们目标就比较明确了,项目正式开始推动起来,就像滚雪球一样越滚越大。
关于世界观的包装,我觉得我们有一些自己的想法,特别是做一款手游,当游戏受到了体量的限制,我们不能去做地图很大的这种游戏,你就不可能让玩家随心所欲地去任何地方,那玩家一定会想为什么我去不了对面那座山,我过不了对面那个河,时候我们一定要给玩家一个合理的解释,让玩家觉得这是一个合理存在的世界。
所以我们的做法,我们在项目上的做法是在世界上当时加了一个设定,比如说这个世界失去了光明,只有在有光的地方才是人类正常可以活动的区域。
那么世界就需要一种发光体,可以让故事可以让剧情,还有整个世界聚焦,非常自然,我就设计了上面生物,它为世界带来光明,人们依附他而活,形成了这个世界观。
所以当时我们决定我们需要一个与世隔绝的被黑雾笼罩的世界。那这里生活的人们的故事以及发掘这背后的秘密自然就成了剧情核心。我们创建的场景就会是生活在世界里的人们的生态环境,同时也需要一个完整的故事链。
主线剧情就一点一点的,主要的人物一点一点的添加进来。然后世界观的设定又不断的完善,再回滚,在整个世界观里面不断的回滚,关卡设计也在不断的更新。最后我们得到了我们想要的故事体系和世界观。
当世界观设定好以后,我就希望世界中的一切体系,一些系统,包括玩法系统都是服务于世界观的。所以当时设计了理智系统,这是一个绝望失控的世界,每个人都有可能在崩溃的边缘,那么主角当然也不例外。他看见的所有的疯狂的事情,或者是这些疯狂会燃尽他的所有的理智,他可能时时刻刻都处在理性和非理性的边缘。
在混乱的世界中,当理智崩溃时会遇到什么?看见的是灵异的怪物,是发狂的boss,还是背叛的队友,这些都是通过游戏的理智系统所表现出来的。但是还是在一个统一的世界观之下,所以这是一个完整的包装,不是说把玩法还有美术,还有剧情全部拆开来处理。我们希望无时无刻的提醒玩家,你正处在一个疯狂的世界中。
画面设定与取巧。当时考虑到我们就这么点人力,还得想办法去节省资源和减少工作量。所以我们做的这个世界观的设定里,外面的世界都处在黑雾中,整个游戏都处在浓雾中,而且光源又很微弱,看不清远处,所以游戏的视距就不用开的很高,以及不用制作一些非常繁琐的细节,也让我们制作的实际体量确实小了很多。
关于上面这块怎么做,我会在后面的场景制作的一个环节里会具体去分析,下面这是我们的一个主角团,还有一个动态的一个状态。
在最开始做角色设计的时候,我们其实有考虑过很多问题,比如手机屏幕比较小,人物占比会比较少,所以在设计的时候会把比例稍微做的夸张一点,物件的厚度都做得比较敦实,没有特别细小的设计,基本上以体块为主,这样的话哪怕东西缩小了,在屏幕上并不是很大,你还是能感受到它的体积感和体块感。
下面这张图是基本的角色制作流程,比如从原画到高模,再到一个材质的绘制。
材质绘制流程上,开始会用painter来对材质进行一个写实的绘制,基本上是走PBR这套基本流程。
因为手机内存非常宝贵,贴图使用有限,我们主要还是把重点放在了材质的调节上,下面是游戏引擎里还原出来的一个实际效果。
在做的时候我们基本上是一个全尺寸贴图,会最终会根据游戏的内存来进行一个优化。
我们基本上贴图不会去专门去压缩,像diffuse和specular可能会看情况进行一些压缩,主要是看内存的盈余,我们深入的去研究了unity的标准的standard的标准材质,而且Substance Painter和unity也做了非常好的衔接,几乎一导出就可以只针对unity5的当时的那个标准材质可以输出。
最终我们用到的贴图有三种,一种是Specular这种金属度或者是粗糙度,基本上是在阿尔法通道里去调整,整体来说用的是一个比较省资源的做法。
这是另一个角色,她的特色是攻击别人的时候,同时可以吸收别人的生命,存在身上的血瓶里,这个血瓶会根据它的自身的攻击,或者是对自身的回血上下浮动变化。
针对这个血瓶,当时我们是用Shader graph来实现效果,并且可以随着人物的位移,你可以看到液体在里面晃动,它基本上是可以保持水平面的一个移动。当然这只是做到一半,最终实际效果要比这个好一点。
这是我们的一个小罐。
主角团和boss我们基本上是使用了一个PBR的流程,但是因为主角或者是boss都是相对单数出现的,所以每个角色的材质球的数量控制可以控制的比较准,我们大概是做了3~4个,分为武器、服装、头头发和皮肤基本上分为这几个材质球。
而普通的怪物在一款ACT游戏里,可能会在一个场景里同时出现多个,所以基础用的材质相对比较简单。虽然说用的比较简单,但是我们还是跟boss是一个生产流程,是用Substance Painter里面来导出出来的传统,只不过说是材质球用的是比较一个传统的材质球,它的一些反射度或者什么,基本上用的是一些反射环境球来模拟的。
下面这是一个boss,游戏里会有非常多的这种非人性boss,给动作确实添了很多麻烦,我们角色有300多根的骨骼,不过是因为在特定战斗场景里只有主角和boss,所以这种消耗也是能消耗得起的,还能接受。
大型boss战我们使用的都是骨骼碰撞,会根据打击点的部位做出IK的受击反馈,比如说弱点受击判断。而小怪基本上使用的是胶囊体碰撞,这就是刚才说过的一个场景里,单个一个怪和很多很多怪,中间要做一个取舍。
然后是场景制作,这里我会举一个具体的例子,我们的阿达米亚的一个场景来解析一下它的制作流程。
从制作思路上来说,第一关结尾的时候,刚刚向玩家展现出了这么一个世界观,玩家刚刚知道头顶的那个大月亮其实是一个我们游戏里的一个巨像,在正对着你。
这一关就希望非常明确的让玩家知道这是一个什么样的世界,所以这一关的主题就是要玩家始终能看到巨像,希望达到的效果就是整个游玩过程中可以看到这个大家伙就一直在你身边行走。
大概确立了剧本以后,首先我会先出这样的一个概念设计图传达出大的思路方向,以及确立一些主要的特殊事件场景,因为当时第一关画面有点阴暗,那希望第二关可以明亮起来,但是又要有那种诡异孤寂的气氛。所以思路明确了以后,就用unity的地形工具,以及简单的一些石块刷,快速出一个layout,这个主要是用来提供给策划,让他们明白整个关卡和气氛还有大的一些结构。
那关卡策划在看了layout以后和概设,他可能大概就明白了,像阿达米亚这样的一个场景,它是一个以悬崖为主题的场景,在接下来进入白盒阶段的时候,就不会因为理解错误而走偏方向。
为什么要做这一步?就是如果你直接让关卡来搭,很有可能会完全气氛上、剧情上,还有一些美术的结合,它不是能很好的结合在一起。所以一开始虽然是多做了一步,但是你只要传达出一个概念或者给出一点元素后,对后期来说其实是会省很多问题的。
到了这一步我们交给关卡设计师进入白盒阶段,在这个阶段就是不断的完善回滚,把角色放进去,不断的测试,不断的测试玩法、测试路线,待整个关卡验证完成以后,那开始用美术资源逐步的代替白盒。
这是一个当时做的关卡的白盒测试,主要是用来测试路线和场景比例,即使是这样,有时候还是会出现比例问题,白盒阶段要搭场景,记得一定要搭得宽大一点,可能会看起来有点空,但是随着中后期,你那些中景或者一些细节东西放进去以后,慢慢会变成一个比较舒适的比例。
我们在做帕斯卡的过程中,确实有好多次做白盒的时候感觉还行,但是小物件一添加后,几乎没有战斗空间,最后只能砍掉重来。所以这也是一个需要注意的点,希望大家引以为戒。
然后是场景的路线优化。在阶段我会要求关卡,策划同学特别注意,因为我们后面会用到剔除遮挡和视锥裁剪这两个东西,所以我们前期的时候规划的时候一定要特别注意,在路线设计的时候,要多转几个弯或者进入室内,或者是你让远处的视野里被一些巨大的物体遮挡住。所以游玩路线也会决定游戏后期的优化方不方便。这主要是控制视野内的模型面数与Draw call。
作为手机游戏在前期的时候规划路线的时候,确实应该要考虑到更多方面。这是刚才说的遮挡剔除。
比如说场景尽量减少出现一条又长又直的路,或者是视野范围特别宽广的地方,比如说像上图绿色的里面的露出,就是绿色部分里露出的远景,其实运算量还是能接受的。
更远处的景其实已经被其他远处的房子剔除掉了,基本上不会参与运算,那如果真的你有特别大的需求,要做一个大的这种大视野的场景,一般这种也是会专门去定制,比如说你要做一个特别大的塔,从底层到高层也都可以看得特别清楚,那你可能只是底层这一段会做的比较精细一点,上面可能也就是透掉了,或者是做简化处理。
然后说到场景材质这一块,场景材质我们基本上是用的Substance Designer来制作,整场景的材质球数量控制是相对比较严格的,基本上30~50之间,一个场景的所有的材质球,但是确实也造成了一些问题。
帕斯卡契约本身场景有一种材质重复度过高的问题,但这就是两边的一个取舍了,你是大的场景、内容,要么内存会爆,要么你就是在视觉上会做出一些妥协。
这是用designer来做的一个砖墙的材质,那designer的最大优势我觉得是可以快速的用连接节点这些,根据需求快速修改,快速迭代,效率会非常高,做出来的东西你也可以根据一些实际的需要进行修改和加工,非常节省成本。
尤其是当场景比较大,特别宏大,需要很多材质需要重复使用时,designer 制作材质它可以重新采样,随机生成一道符合美术风格的新的材质,大大节省了时间成本和人力成本。
我们项目中其实并没有使用 unity的那套地表编辑器,主要是因为我们地表的场景有时候会达到3~4层,而且地表的面积相对也比较窄,用编辑器比较难处理,对后期优化也比较困难,不过是要看具体项目需求的。
如果是项目比较开阔,地图开阔或者平整的话,unity的地图编辑器其实是相对非常成熟的。我们这里其实是做了一个材质球,通过一张MASK贴图来混合两种地表纹理,用顶点色其实也是可以达到相同的目的。
说到灯光这一块,场景制作的场景光照,整个游戏是使用了实时灯光加烘培,加light Probe。这三块那实时灯光这一块的话是角色和怪物的,还有场景里的实时灯光,这三块灯光其实是分开的。其实主要是为了方便调整场景的光线,整体场景用的是一盏mix灯,来提供整个场景的主光线,角色和怪物是用另一盏实时灯光来打整个人身上的明亮度和高光。
烘焙这一块我们主要使用的是混合灯光进行烘焙,模式使用的是Shadow Mask这种烘焙模式我们在用的时候有一个小小的问题,就是它暗部被覆盖的面积比较大时,高光会被这张MASK贴图盖住,会造成整个暗部比较平,针对问题我们使用了两种方法来解决。
一种是在材质上,在场景的本身材质上给一个环境反射贴图,让材质在暗部时看起来也会有高光和立体度。另一种是在一些非常特殊的情况下用的,在材质上模拟一个反向的光,就是让我们的程序员在材质里就写了一盏反向光,它是一些比较特殊的情况在用的。再加上人物走进阴影里的时候,自身会打开一盏点光源,我们在一些山洞里或者是洞穴里,或者是一些黑暗的建筑内部都会这样处理。
烘焙的时候可能有些注意的点就是尽可能减少lighting map张数来控制整体的Draw Call。比如说像我们项目,用了很非常多的预制组件,就是Prefab那是相同的模型和相同的材质,但是由于你不会被分布在两张不同的lighting map上,那它的Draw Call其实是不会合并的。
这也就是有一个非常大的矛盾点,如果你lighting map使用得过多,那Draw Call可能会多,但是如果你使用得少的话,你就要控制住lighting map的尺寸,否则阴影会很模糊。所以lighting map的UVS的分布,一个是会造成阴影模糊,一个是会造成内存增加,这两个是需要你在做项目的时候去进行一些取舍。
关于light Probe,主要我们是用来给一些动态物体附着光影,比如说角色、怪物还有一些可互动的机关,后来我们就发现场景里有一些特别小的物件,其实用烘焙的效果不是很好。
因为那个小物件本身UV就很小,你这张lighting map最后一压缩,那个UV会聚焦在几个像素点上,那个像素点如果你没有处理好的话可能就是黑片。但是如果完全不着色的话,这些物件在暗部和亮部的表现是完全一样的,那就非常奇怪,物体在暗部的时候可能会表现有点亮,它在亮部的时候可能又表现得非常暗。所以我们最后后期就改为使用light Probe进行着色,因为物件本身比较小,你放在那里,放在暗部里,本身会着一个比较暗色的,其实也看不大出来,反而会比你烘焙的效果更好一点。
打光这块,因为场景的重复度比较高,所以我们在制作的时候有一个概念,就是一定要用灯光来给玩家作为记忆点,这就造成了光对我们来说非常重要,使用相同的素材,要根据打光的不同,营造出不同的场景气氛,这点是对我们来说在整个制作场景中的一个难点。
说到整个游戏的阴影。游戏阴影这一块是分为角色阴影、场景阴影,还有一些其他动态阴影。用我们投影的方法其实也是一个较为通用的做法了,用专门的投影相机,按照光照方向给场景、角色拍一个剪影,拍到RT贴图上,再根据投影投射到地表上,这样做的话可以无论再多的怪和角色,那只产生一次Draw Call,超出主角的范围又可以不会被渲染,而且你可以根据这张RT贴图,这张RT贴图的格式设置,你可以做一些处理,还可以加一些抗锯齿什么的。
场景阴影,我们基本上用的就是传统的烘焙阴影,其他动态阴影,比如说像云雾投射下来的这些阴影,基本上是用跟角色一样的,是用RT贴图来实现的。
场景里的物件动画,像植被,还有飘着的旗子什么的这些,我们基本上是用顶点动画来完成的,相对来说比较省资源。除此之外,人走到草上把草压弯是以人物坐标与草的位置远近,程序控制,顶点偏移来实现的。
视距这块是如同前面所说,我们世界观的时候设计的比较讨巧,整个世界是处在黑雾之中,所以我们的这个游戏fog开得非常强。如图例所示,这几个红圈基本上几乎都是雾气了,你里面其实都可以不要有细节了。
那我们只要留下大石头的剪影,还有一些建筑的剪影,其他基本上能关的都关了,这样的话我们做起来其实就是把这些所有的物品进行分组,根据体量分组,越大的物体它的可视范围越远。
例如一些建筑剪影,或者一些造成整个场景的一些大石头,越小的物体它的格式范围越近,基本上参照这个规则,所有的物体会被分到不同的层里,然后去给每一层去做一个可视范围的设置,再加上LOD,这样可以大大的减少消耗。
其实像我们这样做了以后,LOD的工作量也就不是很大了,所以我们游戏里LOD用的并不是很多。
雾气这一块,雾气分为体积雾、定制雾片和基础雾。体积雾我们是用一些Shader模拟的,基本上就是传统God Rays的那种效果,然后定制雾片是用渲染粒子实现的,基本上是我们整个游戏里面的定制雾片,基本上是放到地上的一些模拟流动的云雾,靠近会消失,然后你用软粒子也不会出现硬边,一个比较方便的做法。
镜头调节这一块,因为游戏里的敌兵种类体型跨度都非常大,针对不同的体型和怪物,我们去做了一套专门调节镜头的工具,可以说每一种怪物你锁定他的时候都是专门独立去调节的,你在这个过程中还会去考虑这个怪物它的攻击方式。
比如说远程法师它的攻击抛物线比较高的话,我们镜头当时调的时候,距离和镜头的远近都会拉得相对比较宽一点。
在制作角色面部表情和口型动画上,我们简单的为角色设置了22个面部骨骼点来实现游戏中面部所需要的基础动画,口型和表情其实都是提前设置好的一段动画片段,然后会根据音频调用这些调用融合的这些片段。
对于Blend Tree这一块,对3D游戏来说,不管是手机模拟摇杆,还是手柄摇杆,其实玩家在操控这些角色移动的时候,都可以朝任意方向来进行移动,例如我们当时在设计维奥拉的时候,那锁定目标以后的移动方式,为了拉开和另一个角色泰伦斯的区别,我们大概设计了10种,前后左右、斜上斜下10个动画片段来做融合,这就是当时维奥拉的一个Blend Tree。
除了一般的走路位移动画之外,角色的攻击动画也占据了非常大的一部分资源,其中攻击和受击的逻辑判断非常重要,我们通过结合状态机的参数制,自定义曲线取值,让程序去分析当前的动画逻辑状态,实现角色在攻击动作时的一个目标的判断。
比如说武器判断,根据预定的攻击类型编号,然后去调取相应的攻击碰撞盒来实现这些做法。另外像攻击中是否可以转向,然后攻击碰撞打开的时机,还有连段判断等等,我们在项目制作中其实是花费了大量的时间来去调这些Curve的参数,这些调整的结果都直接影响了整个游戏的手感,特别像动作游戏,你这些手感的好坏其实都去拉这些曲线来实现。
我们整个游戏可能有非常多的工夫是在不停的去调整这些曲线上,然后我们整个角色是用了全身的IK系统,包括人物瞄准、脚步IK,然后收集IK的,比如说现在看到的这张图就是人物站在不同的地表上,脚部骨骼会做出一些变形。
关卡制作,我们在做关卡的时候,其实为敌兵制作了非常丰富的状态机机制,制作了若干种休息动画,隐藏的攻击动画,你会在整个游戏中看到有的怪物它隐藏在角落,在这偷袭你,这些其实都是专门定制的,然后怪物都会有视觉和听觉方向还有范围。
比如说像这张图里黄色的圈,就是一个听觉范围,红色的三角区是视觉范围,如果怪物在没有看见你的情况下,你慢走的话是不会惊醒他们的,但是如果你跑过去可能就会引发他们的攻击。
关卡中是采用了动态加载的方式加载怪物的,加载场景时会把这些怪物预先放到内存里,场景中放了很多点,然后又放了很多专门设置过的这种显示盒,就是这种绿色的盒子,只有角色进入这个绿色的盒子范围内的时候,绿盒子范围内的怪物才会被动态加载,这样的话可以比较稳妥的控制怪物的加载上线,而且也可以比较精确的控制,我想哪些怪显示,哪些怪不用显示。
最后谈一谈过场动画。说到过场动画一般是我跟编剧先聊,聊完确定了大概的剧情,然后先出一个故事板,把脑子里的想法一些画面先具像化,加上策划以及程序来一起推敲修改。
这个阶段主要是确定一些效果是否能实现,如果不行的话,那可能还要商量一个可行的方案,再不断的继续的去修改故事版。
当故事板确定了以后,我们会在max里面去做一个layout,这个主要是用来确认故事结构以及镜头的合理性。
这个阶段不会去加面部表情,加口型,而且会拿给配音去做参考,待他们把配音部分完成以后,那确认没有任何问题,才会继续添加表情和口型。
游戏中有一些比较复杂的过场动画,为了不占用过多的内存资源,我们自定义了一套及时加载系统,在演出完成后也可以立即释放出游戏内存。那根据预设的摄像机,调用角色ID以及相应的过场动画资源,那比如说场景风格,一些灯光和一些音效等等。同时程序也可以通过代码来控制美术的表现。
Unity的Timeline功能非常强大,早期的时候我们其实并没有使用,是用笨的办法,去实现游戏里的一些过场需求。那待unity Timeline功能实现了以后,我们很早的就投入去使用这个东西,然后发现使用了以后确实非常棒,效率直线提升,而且我们结合了自身的项目,设计了一套状态控制器,可以通过判断当前操纵的角色,动态的调用相应的一些演出动画。
另外在一些简短的动画中GamePlay状态下,也可以做一些简单的一镜到底的方式。
以上就是我为大家带来的分享。其实我们并没有用一些特别复杂的,或者是自己自定义的功能,其实用的还是unity本身的强大的那些功能。这些东西的怎么灵活运用?我想,透过我们这个项目、通过今天的分享,能给大家带来一些思考,谢谢!