在今年中国Unity线上技术大会<游戏专场>分享上,来自鹰角网络的海猫与黄一峰分享了初创团队的曲折开发前行之路-《明日方舟》中3D和2D结合方案。其中海猫以游戏设计的视角,黄一峰以技术的视角来共同分析他们在开发过程中遇到的问题以及具体的解决方案。
以下是分享实录:
大家好!我是《明日方舟》制作人海猫络合物。这次的分享我还会请黄一峰和我一起来讲。
今天我们要讲的主题是初创团队的曲折开发之路,主要会结合《明日方舟》的3D和2D的结合方案来进行一些分享。主要由我做前面的一些关于最早概念的介绍,由黄一峰介绍一下具体我们3D和2D结合方案中遇到的问题和具体的解决方案。
首先自我介绍一下,我是海猫络合物,我是《明日方舟》的制作人,也是上海鹰角网络的联合创始人。我主要会负责游戏的UI和一些部分。
简单介绍一下《明日方舟》。《明日方舟》是2017年鹰角网络创立之初立项的第一款游戏,我们也是在那个时候进入了正式开发,在2017年的12月到2019年的3月一共进行了3次测试,在2019年的5月1日终于迎来了全平台的公测。目前《明日方舟》是鹰角网络唯一一款作品,也是我们创业的第一款作品。
这款作品相对来说我们注重的是独特的风格和视觉的表达。由于我们的游戏玩法和视觉表达都有较强的自我风格以及较高的质量,也在上线的时候获得了AppStore的特别推荐。这款游戏具体的玩法可以从图中看到,它是一个由策略、塔防、RPG相结合的玩法,是采用Unity开发的,同时也是考虑到技术的实现,我们采用了一个2D和3D相结合的表现形式。在角色上我们是采用了日式的一个二次元的表达手法,但是不同于大部分的二次元游戏,我们的角色的一部分元素表达和故事世界观以及场景概念设计上的风格都是偏向于写实的。
可以看一下我们最早原先设置的时候是左边一张图,这张图是我们当时用Unity开发的原型,可以看到和目前我们游戏的实际画面是有较大差距的。也是借助与Unity相对的便利性,我们能够在早期进行一个原型的实心,我们采用了一些临时的素材将我们的很多想法付诸现实。
考虑到了一个问题,为什么我们当初最早开发的时候会使用Unity?除了我们自身的经验之外,我们当时也会有一些现实的原因和一些设想,让我们选择了Unity这款引擎。
2016年的时候我和我们的主创黄一峰在家里构思作品,当时我们需要尽快一个大致的共识,为了《明日方舟》的具体风格而定下早期基调。我当时发给了他一张图,就是我们最早奠定世界观的一张图,在这张图之后,我就说我已经准备好开始了,黄一峰当时也回答我说好,那么立刻开始把我们的作品进行具体的实现。
当时刚开始肯定会遇到很多的困境,对于我们来说,当时我们的困境非常之多,尤其是我们很多是大学刚毕业,有些是从业只进行了一个项目,所以人数非常少。所以,面对我们一些具体的情况,我们也做了一些具体的分析。所以对当时的我们来说有一些点是非常明显的,比如我们团队较小,因为我们的状态是一个应届毕业和从业时间不长的状态,我们当时创业团队人数也非常少,只有4到6人,至今的情况也是不多的,并没有像一些创业团队那样可能带了大量的资金或者是大量的团队来,同时,我们自己也是平时接触的作品非常之多,所以对于第一款创业的作品也是提出了很高的质量的要求。
但是很明显的是高要求,而我们又没有较好的技术积累去实现一个心目中非常非常理想的游戏作品,也是缺少一些开发经验,所以,我们当时还需要面对的是缺少经验,又对自己的要求高,那么应该怎么实现?还有一个隐性的条件就是当时的游戏市场也是变幻莫测,即使是现在也是变幻莫测,但是当时对我们来说没有更多的技术积累,所以会更加不清楚自己应该往哪个方向发展。我们对这方面也是进行了一些思考的。
具体看一下当时的情况。我们当时也是非常拮据的,在一个小的公寓内进行开发,大家有种田园牧歌的状态。当时人员比较少的时候我们也发现我们团队中没有相对来说成功3D项目经验的团队,我们在这个基础条件下最初是不会考虑3D开发的部分的,但是很明显我们又想去做那方面,所以我们当时做了一些妥协。比如我们将我们的地图分成了3D。
第二个是我们对质量要求比较高。从现在来看《明日方舟》整个作品的调性中包含了许多我们想要追求的点。比如从这张图上可以看到根据这个圈的大小涵盖范围也可以知道我们许多点是相辅相成的,可能缺一不可,尤其是以日系角色美术为核心,显示风格设计辅助的一个基本美术框架,包括之外还有一个世界观故事的设置。
我们自己追求的另外一个重要的点也是一个有乐趣和深度的game play的部分。
除此之外还有我们的品牌形象和游戏运营和自媒体的风格。我们非常想在我们作品中实现这些点。
从现在来看,《明日方舟》的整体项目有比较多的点上是往写实方向走的。我们当时是采用了自己能够实现的方式去完成我们的作品。比方刚刚提到了一点,我们通过相对偏日系一些的二次元的风格实现我们角色的表现,但是我们想更多地追求一些写实风格的东西,我们在整个故事的框架设计之外向外推导往写实的方向走。所以我们那些活动在整体设计中是有一些设计,让它显得更加自恰,能够符合这个世界观,也能更加符合现代设计。从角色到故事,再从故事到世界观,它有一个风格的推演,越来越写实,越来越偏向我们想要追逐的美术的写实性的表达。
因为我们过去在一些同仁圈,一些创作圈中也尝试去创作过一些同仁游戏,所以我们对自己,不是说我们简单做一个作品就结束了,我们还是希望能够实现一些对自己的超越。很明显的在这些方面都对自己有了比较高的要求。但是,过去因为同仁游戏或者是同仁本的载体相对来说还没有面向那么多的用户,没有影响多那么多的读者或者是玩家,自然要求会变低。但是,我们现在接触的领域是更加大的,所以我们对自己的要求也会变高。
在种种情况之下,我们自己心中想做的作品确实如图上所说的一些,就像赛博朋克2077,我们未来是想尝试往这边做,但是很明显的自己知道当时的能力水平是没有到这个程度的,是做不到这种程度的,我们现在需要找到更加现实的方法完成这一系列。
后来就通过我们自己的一些创作对这个项目进行了一些早期的规划,包括在图中能够看到的,就是刚才发的一张图和我们最早对概念的构想,也得益于我们当时的概念构想形成得比较快,所以后面就对自己的风格把握得比较牢固。在此基础上,另外一条线也能顺利地铺开,对玩法进行一些探究。其实可以看到当时的情况,我们几位成员,还有其他的核心成员这边没有列出来。我们列举了一些在公共场合露过面以及大家可能比较熟悉的成员。
我们每个人都会发现对自己熟悉的领域都有较高的要求。比如我自己需要追求一个比较优秀的视觉设计风格,而黄一峰会要求需要技术选型、品质稳定、可扩展,他对于程序方面有较高的要求,而RUA这边是负责我们的玩法策划,关卡策划,他对自己的玩法深度要求也会非常高,而负责美术总监这边的唯老师对美术品质自然是有非常高的要求的。还有其他的成员也有其他的要求。在这些要求的结合之下,对于我们当时的团队情况来说其实是非常艰巨的,如何在一个我们自己都不太清楚的该是怎么样的项目中实现这些要求,就会遇到很多的问题。
总结下来,我们当时面临的一些困难具体的情况就是小团队,当时只有4到6人,资金也比较少,没有足够的资金去招人或者是铺开一些外包或者是招募更多的人加入设计,对质量,尤其是对美术有着较高的要求,这样我们在3D、2D方面也会产生一些冲突。更关键的是虽然我们有过成功的项目经验,但是大家都很年轻,尤其是3D开发相关的一些经验非常不足。
我们也很明确当时对于3D和2D来说有一个冲突,那我们究竟该怎么做呢?作为一个日式画风,以角色为主的具有高美术要求的作品来说,3D项目的方向可能对我们来说当时是非常不现实的。因为3D项目通常需要更多的美术资源、人手和资金,而通常也是需要大量的时间,还需要大量的投入,我们在没有这些技术的情况下很明显是没有办法实现这些的。但是,我们未来也希望向3D做一些铺垫,所以我们当时没有完全放弃3D方面的一些探索,大家在图中能看到,我们在关卡方面是采用了一些3D,想做一些技术积累,让我们未来能够更好地接触3D方面的一些开发。
我们也会看一下早期的图,我们当时在自己的案板上对游戏最早的风格包括玩法进行了很多的探索。左边看到的是一张非常不太清楚的图,从图上能看到网格化这个设计最早就提出了。大家可以看到中间有一块菱形的场地,这是我们最早关于网格和地图的设置,但是我们也遇到了一个问题就是45度角和90度角该如何排布的问题。后面我们也尝试做了一个概念设计,通过一些快速的素材堆积和简单的探索把我们想要的游戏的感觉尝试做了出来,而这图中有些临时素材跟最后的成品是有表达差距的,不用管它。从这张图中可以看到我们最早想要实现的感觉,在这张图中得到了一些探索,并且一定程度上影响了我们后续游戏的制作风格。
当时在这个情况下,90度角的网格化的设计已经有一些雏形了。我们当时也想通过这个更好地探索我们的游戏。在这种情况下很明显Unity的一些优势就会发挥出来。我们当时也确定了自己的游戏需要以什么形式发布。我们当时瞄准的是手游这块,很明显的跨平台让开发的可能性变得更加多样,这是Unity的一大亮点。
当时的情况是Unity的社区也相对完善,它能够让我们在一个非常初创的缺乏经验的团队里找到比较好的解决方案,让很多的开发困难迎刃而解。同时,以Unity,3D开发的游戏项目,哪怕是软件方面成功案例是相当之多的,也能让我们找到一些技术参照,去我们该采用什么样的方式开发我们的作品,或者说我们未来能够做到什么样的程度。同时,优秀技术支持也让我们想实现的新的东西有更多的可能性。还有一个最关键的就是有很多的小型项目在Unity的帮助下能较好地完成。U3D对于小项目的开发友好性我们认为是非常强的,这也是让我们选择Unity的一个大原因。它作为一款成熟的跨平台商业引擎对我们来说可能是当时最好的选择。
其实在选择完决定采用什么方式进行开发之后,整个过程仍然是有许多困难的,可以用曲折前行这个词来形容。我们在当时用Unity进行了一些快速的原型开发,除了刚才我们说的版本以外,我们还有一些别的版本,我们最早出现了两种原型,一种是我们目前采用的左边这种,和现在的《明日方舟》游戏玩法较为接近的,我们叫做5×5的模型,它和传统塔防不太一样的是它的场地非常之小,采用的角色数量可能较少,并且对于方向和网格的差异性设置要求相对之高。
右边我们也采取了一个模型,有点类似目前常见的传统塔防,它的地图相对之大,它的角色目前我们是没有放上去的,但是我们这个模型中角色的攻击范围没有像现在的《明日方舟》网格化差异是如此大的。它也有一些特点,比如说恢复cost是通过地图上的一些机关来完成的,但是它总体来说有两个问题是造成我们最终没有选择它的原因。一个是它的范围设计不符合我们自己想要做的创新,就是对于网格的差异性让我们每个角色有不同的使用感受。这点是我们选择它的原因之一。
还有一点就是在手机上进行实现的时候,这个地图相对来说较大,体验起来不但角色的表现性相对较弱,对我们美术的表达也造成了困难。所以,我们基于一些玩了以后的体验和感受我们采用了最早的5×5的方案,当然这个地图不是5×5的,但是这是我们的一个统称。
所以,我们最后决定原型之后也能借由U3D的特质,使用我们过去的资产和一些星座的素材快速地迭代。
这边就展示了我们最早的地图的原型,能够让他们看到基本和我们现在的游戏方式是比较接近的,包括角色的方向,一些速度性能,还有一些地图的基本方式,都是相对来说和现在非常接近的。
所以说我们在最后2年的跨度之中将最早的原型基于Unity的想法转化成了一个现实,其实是个很漫长的过程,但是利用Unity有很多便利性,我们能够将我们的想法付诸现实。所以,最终我们认为采用Unity是我们对内容追求的一个最好的方式。我们也通过Unity解决了很多方面的进化,让问题得到快速解决,也让我们有更多的时间去实现我们最早对于质量方面的要求,我们能够把精力放到很多制作上去,最终完成《明日方舟》这样的作品。最终我们上线的时候人数规模差不多达到了30到40人的团队规模,也得益于Unity的U3D一些开发经验较为丰富的社区,我们也能快速地补充人力完成我们对游戏的一些开发。
我大致分享的部分就是这样的。之后我们会让黄一峰介绍一下《明日方舟》具体在2D和3D开发案例中遇到的一些问题。
大家好!我是黄一峰,是《明日方舟》在前期开发当中的技术负责人,也是上海鹰角网络的联合创始人之一。刚刚我的同事海猫从他的视角讲述了《明日方舟》从0到1的故事,接下来我将从我的视角,从更偏技术的角度来讲述为什么我们会选择3D和2D结合的这样一个画面表现方案,我们做出了哪些工程和技术上的取舍,我会尽量以合适的力度讲解,希望能给类似选型的项目一些提示,避免重复踩坑。
接下来是一个大致的大纲。首先我会介绍我们为什么会选择3D和2D结合的方案?而这个角度可能和刚刚海猫讲的不太一样。第二,我会说一下我们方案的具体内容,包括场景和单位两个维度。第三,我会详细地说明我们在开发过程中遇到的三个我们认为比较有典型意义的问题,希望能够给大家带来一些提示。
首先,相信不是所有在座的同学都了解或者玩过《明日方舟》,所以说我会首先播放一段15秒钟的战斗视频,这段视频是来自我们今年夏季的活动“密林悍将归来”。大家可以看到整个画面的风格和这种感觉是偏于2D画面为主的,无论是角色,角色上的特效,角色的弹道以及敌人包括视角是固定的,是一个2D为主的游戏。但是比较特别的是我们在场景的方案上选用了3D的一个模型和偏写实的渲染。我们整个场景的建模包括打光,包括渲染都是用偏写实化的方式实现的,包括制作和渲染都是用标准的PBR为工作流。
这个结合是相对比较罕见的,也是今天我们想描述的一个重点。整个战斗画面的摄像机是非正交的,就是我们传统所说的透视相机,单位和场景的空间关系实际上是比较特别的,接下来我也会在遇到问题的环节详细地进行一个描述,大家可以再看看这个战斗画面。
为什么我们会使用3D和2D结合这样一个方案呢?刚才海猫做了一些讲解。我这边认为比较简单,3D写实风格可以较好地匹配《明日方舟》相对严肃的世界观和我们比较特别的美术风格。而2D的Q版小人可以较好地展现角色的魅力,避免top-down视角的局限性。大家可以回忆一下top-down的游戏,尤其是像我们这种基本是从俯视角看战斗场景的游戏,它的角色的绝大部分都被它的头顶给遮住,所以你看到角色实际上不太能够看到它的动画细节包括身上的服饰细节,你看到的大部分都是个大头。我们为了避免这个问题,决定使用2D Q版小人。当然最重要的问题是我们作为一个初创团队,我们希望能够尽量地降低风险,所以说我们希望能选择相对市面上比较成熟的2D动画方案,而去避免当时我们认为还没有特别好参考的3D小人的方案。当然,现在有很多友商已经做得很好了。
同时,我们想实践3D开发的流程,积累一些3D开发的管线和工作经验,所以我们最后选择了这样一个特殊的选型。
现在这个选型有很多现实因素,但是最后实践下来我们认为它是别具一番风味的,是相当特别的。
好,这张概念刚刚展示过,实际上是由海猫在我们项目早期立项初期创作的一张图,这张图创作的时候我们一行代码都还没有开始写。这张图是为了给整个团队的成员一个统一的认识,我们这个游戏究竟会长成什么样。我们可以从繁琐或者抽象的策划案中具体地落到到这样一个视觉的概念上。
可以看到这张图中的很多要素和我们现在的选型是一致的,包括3D的场景,包括2D的小人这里面模糊掉了,包括整个摄像机的透视的方向其实和我们现在的选型都高度相似的,这也是我们比较幸运的。
大家可以看到比较特别的是左下角有个小人是垂直站在场景上的,但是这个垂直站在场景上的行为符合场景和角色的关系,但是却不符合我们这样一个视角的比较好看的关系,那个像纸片。这个问题也是为之后的开发埋下了一些伏笔。
这张图是我们早期的一些设计和参考图。左边这张图是早期的Q版小人,我们一共有8个小人,而Q版小人上我们的选型和当时主流的头身比小的主题不同,我们选择了相对它的腿和身子会更长一些,头身比相对更大一些,而这个方向我们融合了一些美式Q版小人的风格。
右边这张参考图是ArtStation一位艺术家的作品,但是我们看到,我们认为它非常符合我们对3D场景包括对写实场景的一个审美。为什么?首先它的作画风格是偏风格化的写实,其次,它整个构图是以网格为核心单元的,它并非是以我们最后选用的四边形或者是正方形的往格,而是使用了正六边形的网格。但是总体来说整个这样一个视觉感觉是非常符合我们预期的,所以我们也把它作为我们创作的一个参考。
然后是视觉方案的一个详细的描述。我们分为两部分。第一部分是场景,场景包括3D的网格状地图,地图周边的那些摆件,地图背后的远景,以及地图上可交付的或者是一些装饰性的小物件,所有3D的模型都是使用标准的PBR工作流制作的,在美术同学的雕刻上会特意做一些画面化的风格化的雕刻,但不会追求较低面线的方式实现一个卡通的效果,我们的面数相对还是比较高的。
第二,在贴图绘制上我们会做一些功能化的尝试,但总体来说我们并非做一个比较常见的日式RPG或者是类似游戏的这样一个卡通化的风格,我们希望用更写实的风格做到一些差异化。
在Shader上,我们采用的光照模型是基于Unity Standard Shader修改得到的PBR Shader。之所以不使用Unity默认的Standard Shader是因为我们对它进行了针对性的优化,同时还添加了一些我们所需要的功能。
第二部分,单位。单位包括角色、敌人、第三方单位以及很多可交户的2D物件等等。所有的2D动画我们都是使用Spine骨骼动画软件进行制作的。在着色上我们使用了经过特殊处理的一个Unlit的Shader,它不会受到任何的动态光照和动态阴影的影响,之所以选择这样的方式并非完全源于我们的技术限制,同时也是因为我们经过实验发现如果我们做的更加激进一点的话,整个场景的角色和敌人的辨识度会变得更差,玩家在玩的时候可能不太能分辨出来哪些是他需要关注的东西。
这部分也是接下来我们进一步推进这个画面表现所需要处理的问题,如何平衡game play和一个视觉效果。
我们场景的视觉方案会有这三张图作为最直观的展现。接下来三张图都是我们实际的渲染图。第一张图刚才大家也看到了密林这样的场景,可以看到场景细节和这个地块,而第二个场景是一个熔岩洞窟的场景,第三图是我们故事发生的主要地点龙门夜晚的场景。大家可以看到这三张图都是在建模式上面我们使用了高度抽象化的以格点为核心的构架的方式,整体的光照细节、模型贴图细节以及一些周边的装饰系,像一些建筑物和一些管道都是非常写实的。
我们的整个视觉方案如下,首先我们的场景是使用Unity PBR渲染模型的,在Shader上我们采用的是略微优化和修改后的BRDF2,在性能上进行了一些调优,并且添加了我们可着色的阴影,在PBR Shader层面实现了高度物,也适配我们某些场景一些特殊的效果。
在Lightmap上面,我们在Shader里面对Lightmap的编码和解码进行了一些特殊处理,使它在所有平台上能达到一致性更好的效果。这点我之后会在问题阶段详细描述它的细节。
我们每个场景都会使用Unity静态烘焙的方案,会烘出两张图,一张Lightmap,一张Shadowmap,所以说会有比较细腻的光影和阴影的表现。在打光方案上会有一盏混合动态光,这相当于我们在运行时只有一盏动态光会配很多静态烘焙光的方式来做打光方案,并且在特殊的情况下我们会添加更多的探针做一些静态的反射,为某些场景添加一些必要的视觉效果。
除了整个模型之外,我们在场景上会添加一些Unity提供的添加方案所添加的产生的滤镜特效和模型特效。
大家可以看到刚刚的视频中是有一个瀑布的,就是用特效实现的,会增加一些风味。
接下来是角色的视觉方案。我们绝大部分的角色在右边这张图中可以看到,我们的SPINE工程当中实际是用了正反两个面做每个角色的。为什么这么做?我们参考了类似的游戏,很多2D游戏实际上只有正面一面,但是在动作上会刻意地避开像冲刺、穿刺这样方向性很强的动作,而选择画面中类似克德克萨斯使用的半圆的圆弧斩的方式,这样能模糊方向性,但是这样的话会极大地限制我们美术工作者对于动作的创作包括武器创作,所以在权衡之后,我们还是选择了把绝大部分角色做两面,做一个动作的拆分,而其他的角色,不太重要的第三方单位,我们就会使用单面的方式。
而整个这样一个方式可以看到我们在正面和反面的转变过程中我们是做了一个类似于纸片人的转变的动画。而这个动画我们的灵感来自于任天堂一款著名的游戏系列《纸片马里奥》里面一个类似的画面,对比看一下,我们游戏的效果和这个是比较接近的,可以看到灵感来源是这里。
好,接下来我会详细地描述几个在开发过程中遇到的问题。这些问题其实都是源自于我们融合3D场景2D角色做一个结合。因为这个方案比较少见,所以遇到问题也比较少见,希望给大家带来一些提示。
首先第一个是空间关系错误,刚刚我也已经提到过,我们场景和摄像机,摄像机并不是垂直于场景,它实际上和场景的X、Y平面呈一个60度夹角的关心,而角色,因为我们要展现角色,肯定是对着场景,对着摄像机,它是垂直于场景的方向的,通过简单的几个关系可以得出场景的X、Y平面和角色的夹角实际上是30度,也就是说我们的角色并不是站在场景上,而是斜躺在场景上,或者说我们是躺在场景上,它实际上是一个斜插的东西,它的结果可能是极易穿模,这里说可能不太直观,大家可以看一下这张图。
最左边的图就是我刚刚描述的合理的空间关系,大家由于角色后面的地块它的模型非常高,所以说它的头是插在模型当中的,进行了一个穿模。
为了解决这个问题,有的同学可能会说把这个角色给调整到垂直场景不就解决问题了吗?那么我们最右边这张图就是把角色调整到垂直于场景,这个时候它和场景的关系对了,深度关系也对了,但是我们看起来非常奇怪,像纸片人。
这种情况下,如果我们调整一下摄像机的角度,比如像中间这张图一样,调整到能够正常地平视这个角色,那整个空间关系看起来是正确的,只是这样一来我们的游戏是没法玩的,因为摄像机只能以这个角度去看的话玩家是没法操作的。
为了解决这个问题,我们最后达到的效果是希望像左边这样,但是能解决穿模的问题。这其中曾经经历了一个错误的思路,也就是说我们渲染的时候关闭了一些test,同时Z-write也不大,我们把整个场景中的模型、摆件和角色都通过一个深度混排的方式,我们手动对它排序,类似于传统2D游戏的处理方式,我们手动排序之后手动去归置,这样确实能达到相对比较正确的结果,但是会带来两个主要的问题。第一个就是我们会破坏这个合批,打破它静态的一个batching,为什么?因为我们整个场景是一个静态,包括它的光照贴图和阴影贴图,我们在渲染的时候可以用相当低的DrawCall做到所有的场景,绝大部分场景的DrawCall都在个位数。如果需要混排,需要打乱角色前、角色后的顺序,我们会增加非常多的DrawCall。
其次,我们会有一些小摆件,比如场景上的一些树木是跨两个格点的,这些小摆件我们大家对它进行排序就很难知道它到底在哪一层。
最后我们解决的思路是让角色需要看起来垂直于摄像机,但实际上它是垂直于场景的。这个听起来有点抽象,待会儿我们会展示图片。那么我们解决方案实际上是把深度进行一个调整,在Unity当中百位或者是在场景当中的位置和着色系它的角色都是垂直于摄像机的,也就是躺在场景上的。而在Vertex Shader最后我们会把深度从刚刚那个空间变换到垂直于场景的空间,这样以来对于深度测试和深度写入来说就好像角色是垂直于场景上的。
左边这张图就是一个正常的透视关系,也就是说角色是躺在场景上,会穿模的情况,实际上最后做深度测试的时候,我会把它角色的深度从刚刚左边这个图变换到右边这个深度空间当中,你可以看到整个角色现在是垂直于场景,并且被抽起来的,它变得更拉长了。为什么?这张草稿能说明问题,首先这个camera是我们的事件方向,它和场景是有一个夹角的,角色垂直于这个camera的方向,它的夹角和场景夹角是30度,这个时候我们可以做这样的一个三角形,而这个三角形的斜边就是我们箭头指的方向,就是我们在深度测试的时候实际上所在的位置,可以发现这上面线上的每个点和原本角色上的每个点是一一对应的。通过几个简单的关系,这是一个直角的三角体,而且是一个30度夹角的,斜边和对边的比例是1:2,所以说实际上这个边的长度是它的2倍。
这里我不会深入一些处理的细节,因为我相信这个比较容易的,通过大家的计算都可以得到。只需要说一点,做这个变换只需要在Vertex Shader在最后做一个深度变换可以,这需要注意的是这个时候Vertex Shader最后的位置它实际上是处于透视除法之间骑士空间当中的,所以此时如果要做一个Z轴的变化在骑士空间中需要考虑到第四位W参与运算,这里是个简单的代码。
好,那么问题解决了吗?其实并没有。我们在整个视觉方案当中还遇到了很多别的问题,刚刚提到的是其中最重要的点而已。这里图中说明的是另外一个问题,我们的干员重兵他的攻击方式比较特别,他的攻击方式是往下挥鞭的时候纵深会特别长,所以说会直接穿到这个模型里面,如果我们把它的角色深度拉伸到垂直于场景,它依然会穿进去,所以此时我们做了一个特殊处理,当它的高度大于等于0的部分我们使用刚刚说的处理方式,而高度小的部分我们使用另外一套处理方式,使这个鞭子被旋转到平行于这个场景的X、Y平面,这样才能在同样正确并且一致的条件下正确地绘制出来。
除了图纸之外,还有空中,它其实处理方式也是不太一样的。所以,这里是有很多细节的,如果大家感兴趣,接下来我们再详细探究。
第二个问题是Lightmap不一致的问题,而这个问题很多友商包括很多网友在网上也提到过,我也看到很多文章,他们会发现编辑器在实机,在移动平台上可能最后Lightmap的结果都不太一样,但是我们调研得到的结果是如果抛开Unity版本谈这个问题是没什么意义的,因为每个Unity版本对于Lightmap编码解码的细节都有一定的调整。所以我们这里所有的结论是在2017 LTS版本上。这个问题的原因是因为光照贴图存储的并不是颜色,它和通常的图是不一样的,它存储的是一个间接光的,它的范围是在0和1之外的,我们无法用一个常规的LDR的贴图格式把它存下来,它原本是一些APBR的信息。所以说我们需要把它进行编码,才能重造一些LBR的贴图格式。那么这个编码的方式在不同平台上是不一样的,这个原因也导致了最后不同平台上的表现结果不一致。
大家可以看这两张图,可能不太容易看清,在明暗交界的地方实际上那个阴影会泛蓝紫,这个蓝紫就是阴影的细节,在左边这张图是被吞掉了,这个细节是我们需要处理的。
这里我不会详细地描述RGBM和WLDR编码,大家如果感兴趣,如果不了解的话,网上稍微查一查应该比较容易了解。笼统来说RGBM会将额外的信息存储到第四个通道alpha当中,而WLDR的方式比较暴力,它直接把RGB的原始信息除以2乘下来,所以它丢失的信息比较多。
接下来是一个具体的问题,当Lightmap光照贴图被烘焙出来之后,它的TextureType默认是设置到Lightmap,那么这种情况下Unity就会根据当前所选择的平台来编码这个Lightmap,影响采样的结果。如果在PC上我们把Lightmap Quality成为High的话,它存储的是一个原生的HDR的信息,如果把它作为Normal Quality,它会把HDR信息通过RGBM进行编码,存在一张LDR的贴图里面去,如果是iOS的安卓,也就是移动平台,它会比较暴力的把所有这样的信息都给编码成double LDR的方式。而double LDR的方式下,alpha 会直接丢弃,这才是我们想通过做一些操作把一些信息存到alpha通道当中,你读不出来的是读不出来的,读出来的是个常量。
接下来是我们做测试的一些细节。这些细节今天我不会展开,大家如果感兴趣可以会后通过PPT的方式查看。
结论来说,如果我们继续保持Unity的默认选择 TextureType -Lightmap,它就已经存储为double DR,LDR的格式了,那double DR的格式只能存储0到2的亮度范围,亮度2以上的范围都被截断和丢失了,为了我们达到更好的效果,在不同的平台上使用RGBM编码,我们必须采取一个default的格式。
具体的方案是我们把烘焙出来的光照贴图的TextureType从Lightmap改为default,同时我们把RGBM的alpha通道这个信息从Lightmap当中抽离出来,放入shadowmask的green chanel,这个原因是因为shadowmask实际上使用了它的red chanel通道,其他通道是没有被使用的。我们为了让两张贴图都可以不存alpha通道,最大化地利用内存空间,我们把alpha做了一个trick的操作,这样以来我们就可以用任意我们喜欢的压缩 格式,包括STC、ETC2和PVRTC对这两张shadowmask和lightmap进行处理。
我们会修改GBR的shader,用RGBM来解码这个lightmap,并使用从shadowmask中读取的信息,也就是刚才说的green chanel的信息来辅助这个解码。在PC上当然也是需要相应地修改兼容,使所有平台上达到一致的效果。
最后这张图就是我们经过这样一个处理方式之后在所有平台上包括编辑器,包括PC五,包括安卓、iOS都达到的细节的光照贴图的效果。
好,最后一点,我们如何融合3D场景2D角色的渲染表现?这个问题实际上是一个比较复杂的问题,我们现在也在探索。我们总结了几点:
首先第一个是我们会对每个主题的场景定义一套作用于所有单位、所有角色的tint color,使其着色和场景氛围更接近。也就是说我们每个场景里面角色的渲染其实略微有些区别,而这个区别的tint color是由我们美术工作人员做配置的,第二点,通过美术处理能够调整3D场景、2D角色,包括整个特效的整体氛围和色调,使它更加融洽。
我们也会除了刚才的tint color之外提供一些后处理的选项,包括color grading和Bloom等等的让美术工作人员能通过他们的努力使我们整个场景3D和2D更加协调。未来我们也会探索更多的方式融合这一特殊的画面表现。
最后做一个总结。《明日方舟》3D和2D结合的方案我们首先使用了PBR的渲染和工作流去处理这个3D模型的场景。然后对于2D的角色,我们使用Spinn的骨骼化软件,使用unlit的shader去处理的。
第二点,为了解决3D场景、2D场景空间透视关系错误的不协调的问题,我们对shader进行修改,在深度上做了一个变换,使它看起来和实际深度当中的表现是不一致的。
第三点,我们自定义了我们Lightmap的编码和解码流程,使其在不同的平台上都能得到一个一致且更好的效果。
第四点,我们使用了一些定制化的tint color和一些后处理的选项,让3D场景和2D角色能融合得更好。
最后,我们提供了这么多的选项是让我们的美术工作人,也就是说我们的艺术家们来做最后的处理的。因为我相信技术人员只是提供工具,最后的整个画面效果肯定还是需要以更加感性的认识去调整的。
今天的分享就到此结束。谢谢大家。再见。