游戏快报

鹰角联合创始人分享:《明日方舟》的前世今生和踩过的坑

鹰角联合创始人分享:《明日方舟》的前世今生和踩过的坑

分享/海猫&黄一峰 整理/菲斯喵

在11月19日晚的 Unity 线上技术大会中,上海鹰角网络的两位联合创始人——黄一峰&海猫,分享了《明日方舟》在早期的开发历程。

海猫从设计与概念的角度讲述了《明日方舟》美术风格的成型与世界观的演变过程;黄一峰则从技术角度,详细讲解了游戏中 3D 与 2D 表现结合的实现方案以及具体技术难点的解决思路。

现如今,随着市场环境与用户需求的变化,不少初创团队也想尝试开发 3D 项目。但 3D 项目成本高,经验不足的小团队难以驾驭。《明日方舟》团队在这一方面进行了折中的思考和尝试,他们的分享或许能够给开发者带来一定的参考。 

海猫:

今天我们要讲的主题是「初创团队的曲折开发之路」,主要会结合《明日方舟》的 3D 和 2D 的结合方案来进行一些分享。我会做一些关于最早概念的介绍,由黄一峰分享我们 3D 和 2D 结合方案中遇到的问题和具体的解决方案。

首先自我介绍一下,我是海猫络合物,我是《明日方舟》的制作人,也是上海鹰角网络的联合创始人。我主要负责游戏的 UI 和文案部分。

《明日方舟》是2017年鹰角网络创立之初立项的第一款游戏,我们也是在那个时候进入了正式开发。从2017年的12月到2019年的3月之间,我们一共进行了3次测试;在2019年的5月1日,我们的游戏终于迎来了全平台的公测。

微信图片_20201123111215.jpg

这款游戏具体是一个由策略、塔防、RPG相结合的玩法。对我们来说,我们相对注重的是游戏独特的风格和视觉的表达。《明日方舟》是采用 Unity 开发的,同时也是考虑到技术的实现,我们采用了一个 2D 和 3D 相结合的表现形式。

微信图片_20201123111217.jpg

在角色上,我们采用了日式二次元的表达手法,但是不同于大部分的二次元游戏,我们的角色的一部分元素表达和故事世界观以及场景概念设计上的风格都是偏向于写实的。

我们最早原先设置的时候是左边一张图,这张图是我们当时用 Unity 开发的原型,可以看到和目前我们游戏的实际画面是有较大差距的。

微信图片_20201123111248.jpg

为什么我们当初会使用 Unity 开发游戏?除了自身经验之外,当时也有一些现实的原因和设想,让我们选择了 Unity 这款引擎。

2016年,我和我们的主创黄一峰在家里构思作品。我当时发给了他一张图,那是我们奠定世界观的一张图,在这张图之后,我说我已经准备好开始了,黄一峰当时也回答我说好,那么立刻开始把我们的作品进行具体的实现。

微信图片_20201123111318.jpg

但我们当时的困境非常之多。其中有一些点是非常明显的,比如我们团队较小。我们团队当时是一个应届毕业和从业时间不长的状态,人数也非常少,只有4到6人。所以我们并没有像其他一些创业团队那样可能带了大量的资金或者是大量的人来做游戏。

同时,我们自己平时接触的作品非常之多,所以对于第一款创业的作品也是提出了很高的质量的要求。

微信图片_20201123111321.jpg

可我们没有较好的技术积累和经验去实现一个心目中非常非常理想的游戏作品。该怎么办呢?当时的游戏市场也是变幻莫测,所以我们会更加不清楚自己应该往哪个方向发展。

我们对这些情况进行了一些具体的思考。我们当时在一个小公寓内进行开发,大家有种田园牧歌的状态。但我们发现,团队中没有人做过相对成功的3D项目,大家没有经验。在这个基础条件下,我们最初不会考虑 3D 开发的部分。但我们又想去做 3D。所以,我们当时做了一些妥协,比如将游戏的地图做成了 3D。

微信图片_20201123111324.jpg

第二,我们对质量要求比较高。从现在来看,在《明日方舟》整个作品的调性中包含了我们许多想要追求的点。比如在这张图中,根据这个圈的大小覆盖范围,你可以知道我们许多点是相辅相成的,尤其是以日系角色美术为核心,以写实风格设计为辅助的一个基本美术框架,此外还有一个世界观故事的设置。

微信图片_20201123111326.jpg

我们追求的另外一个重点,是有乐趣和有深度的 Gameplay。除此之外,还有我们的品牌形象和游戏运营和自媒体的风格。我们非常想在自己的作品中实现这些点。

从现在来看,《明日方舟》整体是往写实方向走的。我们当时是采用了自己能够实现的方式去完成我们的作品。比方刚刚提到的一点,我们通过相对偏日系的二次元的风格来实现角色的表现。

但我们想更多地追求一些写实风格的东西。我们在整个故事的框架设计之外,向外推导,往写实的方向走。从角色到故事,再从故事到世界观,它有一个风格的推演,越来越写实,越来越偏向我们想要追求的美术的写实性的表达。

微信图片_20201123111329.jpg

过去,我们也尝试创作过一些同人游戏,所以我们对自己,不是说我们简单做一个作品就结束了,我们还是希望能够实现一些对自己的超越。同人游戏或者是同人的载体相对来说还没有面向那么多的用户,没有影响多那么多的读者或者是玩家,自然要求会变低。但是,我们现在接触的用户范围是更加大的,所以我们对自己的要求也会变高。

在种种情况之下,我们自己心中想做的作品确实如图上所说的一些,就像《赛博朋克2077》。我们未来是想尝试做这样的作品。但是很明显的,自己知道当时的能力水平是没有到这个程度的,我们现在需要找到更加现实的方法完成这一系列。

微信图片_20201123111335.jpg

后来,我们通过自己的一些创作对《明日方舟》进行了一些早期的规划,比如我发给黄一峰的画,就是我们最早的游戏概念构想。得益于我们当时的概念构想形成较快,后来我们对自己的风格把握得也比较牢固。在此基础上,玩法这一条线也能顺利地铺开。

其实可以看到当时的情况,我们每个人都对自己熟悉的领域有较高的要求。比如我追求的是优秀的视觉设计风格;而黄一峰会要求技术选型、品质稳定、可扩展,他对于程序方面有较高的要求;RUA 负责游戏的玩法策划,关卡策划,他对游戏的玩法深度要求也会非常高;美术总监唯老师对美术品质自然是有非常高的要求的。还有其他的成员也有其他的要求。

微信图片_20201123111337.jpg

在这些高要求的结合之下,我们当时的团队面临的挑战其实非常艰巨。因为在一个我们自己都不太清楚的该如何实现这些要求的情况下,团队会遇到很多问题。

总结下来,我们当时面临的一些具体困难就是:

  • 团队小,只有4到6人;

  • 资金也比较少,没有足够的资金去招人或者是请外包;

  • 对美术有较高要求,导致在3D、2D方面会产生一些冲突;

  • 更关键的是,大家都很年轻,3D开发相关的一些经验非常不足。

微信图片_20201123111340.jpg

那我们究竟该怎么做呢?作为一个日式画风,以角色为主的具有高美术要求的作品来说,3D 项目的方向可能对我们来说当时是非常不现实的。但我们当时没有完全放弃 3D 方面的探索。我们在关卡方面是采用了 3D 表现,我们还是想做一些技术积累,让我们未来能够更好地接触 3D 方面的一些开发。

当时,我们在自己的案板上对游戏最早的风格包括玩法进行了很多的探索。左边是一张非常不太清楚的图,图上能看到网格化这个设计——大家可以看到,中间有一块菱形的场地,这是我们最早关于网格和地图的设计。

微信图片_20201123111343.jpg

但是我们也遇到了一个问题:就是45度角和90度角该如何排布的问题。后来我们也尝试做了一个概念设计,通过一些快速的素材堆积和简单的探索,把我们想要的游戏的感觉尝试做出来。

这图中有些临时素材跟最后的成品是有表达差距的。但你从这张图中可以看到我们最早想要实现的感觉。我们在这张图中得到了一些探索,并且一定程度上影响了我们后续游戏的制作风格。

当时,90度角的网格化的设计已经有一些雏形了。在这种情况下,Unity 的一些优势就发挥出来了。我们当时已经确定了游戏需要以什么形式发布。很明显的,跨平台让开发的可能性变得更加多样,这是 Unity 的一大亮点。

微信图片_20201123111346.jpg

Unity 的社区也相对完善,它能够让我们这样一个非常初创的、缺乏经验的团队找到比较好的解决方案,以 Unity 3D 开发的游戏项目,哪怕是软件方面的成功案例也是相当之多的。

同时,优秀的技术支持,也能让我们想实现的新的东西有更多的可能性。

还有一个最关键。我们认为,Unity 3D 对于小项目的开发友好性是非常强的,这也是让我们选择 Unity 的一个大原因。它作为一款成熟的跨平台商业引擎对我们来说可能是当时最好的选择。

其实在选择完决定采用什么方式进行开发之后,整个过程仍然是有许多困难的,可以用「曲折前行」这个词来形容。我们当时用 Unity 进行了一些快速的原型开发,除了刚才我们说的版本以外,我们还有一些别的版本。

我们最早出现了两种原型,一种是我们目前采用的左边这种,和现在的《明日方舟》游戏玩法较为接近的,我们叫做5×5的模型,它和传统塔防不太一样的是它的场地非常之小,采用的角色数量可能较少,并且对于方向和网格的差异性设置要求相对较高。

微信图片_20201123111349.jpg

右边我们也采取了一个模型,有点类似目前常见的传统塔防,它的地图相对之大,它的角色目前我们是没有放上去的,但是我们这个模型中角色的攻击范围没有像现在的《明日方舟》网格化差异是如此大的。它也有一些特点,比如说恢复 cost 是通过地图上的一些机关来完成的。

总体来说,有两个问题造成我们最终没有选择它。一个是它的范围设计不符合我们自己想要做的创新,就是对于网格的差异性让我们每个角色有不同的使用感受。还有一点就是在手机上进行实现的时候,这个地图相对来说较大,体验起来不但角色的表现性相对较弱,对我们美术的表达也造成了困难。

所以,我们基于一些玩了以后的体验和感受我们采用了最早的5×5的方案。

我们决定原型之后,也能借由 U3D 的特质,使用我们过去的素材和一些新做的素材快速地迭代。

下面这张图展示了我们最早的地图原型。你能看到,它基本和我们现在的游戏方式是比较接近的,包括角色的方向,一些速度性能,还有一些地图的机制等。

微信图片_20201123111352.jpg

在最后 2 年的开发之中,我们将最早的原型基于 Unity 3D 转化成了一个现实。这是个很漫长的过程,但得益于 Unity 的诸多便利性,我们能够将自己的想法付诸现实。所以,我们认为采用 Unity 是我们对内容追求的一个最好的方式。我们也通过 Unity 解决了很多方面的进化,让问题得到快速解决,也让我们有更多的时间去实现我们最早对于质量方面的要求,并最终完成了《明日方舟》这样的作品。

微信图片_20201123111354.jpg

最终我们上线的时候,团队规模差不多达到了30到40人。也得益于Unity的 U3D 一些开发经验较为丰富的社区,我们也能快速地补充人力完成我们对游戏的一些开发。

我的分享部分大致就是这样。之后我们请黄一峰介绍一下《明日方舟》具体在2D和3D开发案例中遇到的一些问题。

黄一峰:

大家好。我是黄一峰,我是《明日方舟》在前期开发当中的技术负责人,也是上海鹰角网络的联合创始人之一。

刚刚,我的同事海猫从他的视角讲述了《明日方舟》从0到1的故事,接下来我将从技术的角度来讲述为什么我们会选择 3D 和 2D 结合的这样一个画面表现方案,以及我们做出了哪些工程和技术上的取舍。

我会尽量以合适的力度来讲解,希望能给类似选型的项目一些提示,避免重复踩坑。

这是我的分享内容的一个大纲。

微信图片_20201123111358.jpg

首先,我会介绍我们为什么会选择3D和2D结合的方案。第二,我会说一下我们方案的具体内容,包括场景和单位两个维度。第三,我会详细地说明我们在开发过程中遇到的三个我们认为比较有典型意义的问题,希望能够给大家带来一些提示。

相信不是所有人都了解或者玩过《明日方舟》。大家可以看一下这张图。

微信图片_20201123111359.jpg

游戏整个画面的风格和感觉是偏于 2D 画面为主的。无论是角色,角色上的特效,角色的弹道以及敌人包括视角是固定的,它看起来都是一个 2D 为主的游戏。

但比较特别的是,我们在场景的方案上选用了 3D 的模型和偏写实的渲染。我们整个场景的建模包括打光,包括渲染都是用偏写实化的方式实现的,包括制作和渲染都是用标准的 PBR 为工作流。

这种结合是相对罕见的。整个战斗画面的摄像机是非正交的,就是我们传统所说的透视相机,单位和场景的空间关系实际上是比较特别的。

为什么我们会使用 3D 和 2D 结合这样一个方案呢?首先,我认为,3D 写实风格可以较好地匹配《明日方舟》相对严肃的世界观和我们比较特别的美术风格。

其次,2D 的 Q 版小人可以较好地展现角色的魅力,避免 top-down 视角的局限性。大家可以回忆一下top-down的游戏,尤其是像我们这种基本是从俯视角看战斗场景的游戏,它的角色的绝大部分都被它的头顶给遮住,所以你看到角色实际上不太能够看到它的动画细节包括身上的服饰细节,你看到的大部分都是个大头。我们为了避免这个问题,决定使用 2D Q版小人。

当然,最重要的问题是我们作为一个初创团队,我们希望能够尽量地降低风险。我们希望能选择市面上比较成熟的2D动画方案,而去避免当时我们认为还没有特别好参考的 3D 小人的方案。当然,现在有很多友商已经做得很好了。

同时,我们想实践 3D 开发的流程,积累一些 3D 开发的管线和工作经验,所以我们最后选择了这样一个特殊的选型。

微信图片_20201123111403.jpg

现在这个选型有很多现实因素,但是最后实践下来我们认为它是别具一番风味的,是相当特别的。

这张概念刚刚海猫也展示过了。

微信图片_20201123111405.jpg

实际上,它是由海猫在我们项目早期立项初期创作的一张图,这张图创作的时候我们一行代码都还没有开始写。这张图是为了给整个团队的成员一个统一的认识,我们这个游戏究竟会长成什么样。我们可以从繁琐或者抽象的策划案中具体地落到到这样一个视觉的概念上。

可以看到,这张图中的很多要素和我们现在的选型是一致的,包括 3D 的场景,包括 2D 的小人这里面模糊掉了,包括整个摄像机的透视的方向其实和我们现在的选型都高度相似的。这也是我们比较幸运的。

大家可以看到,比较特别的是左下角有个小人是垂直站在场景上的,但是这个垂直站在场景上的行为符合场景和角色的关系,却不符合我们这样一个视角的比较好看的关系。它就像个纸片。这个问题也是为之后的开发埋下了一些伏笔。

这张图是我们早期的一些设计和参考图。左边这张图是早期的 Q 版小人,我们一共有8个小人。在 Q 版小人上,我们的选型和当时主流的头身比小的风格不同,我们的选型,腿和身子会更长一些,头身比相对更大一些。而这个方向,我们其实融合了一些美式 Q 版小人的风格。

微信图片_20201123111407.jpg

右边这张参考图是 ArtStation 一位艺术家的作品。我们认为它非常符合我们对 3D 场景包括对写实场景的一个审美。为什么?首先它的作画风格是偏风格化的写实;其次,它整个构图是以正六边形网格为核心单元的,并非是以我们最后选用的四边形或者是正方形的网格。所以,我们也把它作为我们创作的一个参考。

然后是视觉方案的一个详细的描述。我们分为两部分。第一部分是场景,场景包括3D的网格状地图,地图周边的那些摆件,地图背后的远景,以及地图上可交互的或者是一些装饰性的小物件。

微信图片_20201123111408.jpg

所有 3D 的模型都是使用标准的 PBR 工作流制作的,美术同学会特意做一些风格化的雕刻,但不会追求较低面线的方式来实现卡通效果。我们的面数相对还是比较高的。

第二,在贴图绘制上我们会做一些功能化的尝试。不过,总体上来说,我们不是做一个比较常见的日式 RPG 或者是类似游戏的这样一个卡通化的风格。我们希望用更写实的风格做到一些差异化。

在 Shader 上,我们采用的光照模型是基于 Unity Standard Shader 修改得到的 PBR Shader。之所以不使用 Unity 默认的 Standard Shader,是因为我们对它进行了针对性的优化,同时还添加了一些我们所需要的功能。

在视觉方案上,我们要讲述的第二部分是单位。单位包括角色、敌人、第三方单位以及很多可交互的 2D 物件等等。所有的 2D 动画我们都是使用 Spine 骨骼动画软件进行制作的。

微信图片_20201123111410.jpg

在着色上,我们使用了经过特殊处理的一个 Unlit 的 Shader,它不会受到任何的动态光照和动态阴影的影响。之所以选择这样的方式,并非完全源于我们的技术限制,同时也是因为我们经过实验发现如果我们做的更加激进一点的话,整个场景的角色和敌人的辨识度会变得很差,玩家在玩的时候可能不太能分辨出来哪些是他需要关注的东西。

这部分也是我们在进一步推进画面表现时所需要处理的问题:如何平衡 Gameplay 和视觉效果。

我们的场景的视觉方案会有这三张图作为最直观的展现。

微信图片_20201123111413.jpg

这三张图都是我们实际的渲染图。我们使用了高度抽象化的以格点为核心的构架的方式,整体的光照细节、模型贴图细节以及一些周边的装饰系,像一些建筑物和一些管道都是非常写实的。

我们的整个视觉方案如下:

微信图片_20201123111417.jpg

首先我们的场景是使用 Unity PBR 渲染模型的,在 Shader 上我们采用的是略微优化和修改后的 BRDF2,在性能上进行了一些调优,并且添加了我们可着色的阴影,在 PBR Shader 层面实现了高度写实,也适配我们某些场景一些特殊的效果。

在 Lightmap 上面,我们在 Shader 里面对 Lightmap 的编码和解码进行了一些特殊处理,使它在所有平台上能达到一致性更好的效果。这点我之后会在问题阶段详细描述它的细节。

我们每个场景都会使用 Unity 静态烘焙的方案,烘出两张图,一张 Lightmap ,一张 Shadowmap,所以说会有比较细腻的光影和阴影的表现。

在打光方案上会有一盏混合动态光。这相当于我们在运行时只有一盏动态光会配很多静态烘焙光的方式来做打光方案,并且在特殊的情况下我们会添加更多的探针来做一些静态的反射,为某些场景添加一些必要的视觉效果。

除了整个模型之外,我们在场景上会添加一些 Unity 提供的添加方案所产生的滤镜特效和模型特效。

接下来是角色的视觉方案。我们绝大部分的角色在右边这张图中可以看到,我们的 SPINE 工程当中实际是用了正反两个面做每个角色的。

微信图片_20201123111419.jpg

为什么这么做?我们参考了类似的游戏。很多 2D 游戏实际上只有正面一面,但是在动作上会刻意地避开像冲刺、穿刺这样方向性很强的动作,而选择画面中类似「德克萨斯」使用的半圆的圆弧斩的方式,这样能模糊方向性,但是这样的话会极大地限制我们美术工作者对于动作的创作。

所以在权衡之后,我们还是选择了把绝大部分角色做两面,做一个动作的拆分,而其他的角色,不太重要的第三方单位,我们就会使用单面的方式。

我们在正面和反面的转变过程中,实际上是做了一个类似于纸片人的转变的动画。而这个动画我们的灵感来自于任天堂一款著名的游戏系列《纸片马里奥》里面一个类似的画面。

微信图片_20201123111422.jpg

接下来我会详细描述几个在开发过程中遇到的问题。这些问题其实都是源自于我们融合 3D 场景 2D 角色做一个结合。因为这个方案比较少见,所以遇到问题也比较少见,希望给大家带来一些提示。

首先是空间关系错误。刚刚我也已经提到过,我们的场景里的摄像机,并不是垂直于场景,它实际上和场景的X、Y平面呈一个60度夹角的关系。而角色,肯定是对着场景,对着摄像机,它是垂直于场景的方向的。

微信图片_20201123111425.jpg

通过简单的几个关系可以得出场景的X、Y平面和角色的夹角实际上是30度,也就是说我们的角色并不是站在场景上,而是斜躺在场景上,或者说我们是躺在场景上,它实际上是一个斜插的东西,它的结果可能是极易穿模,这里说可能不太直观,大家可以看一下这张图。

微信图片_20201123111428.jpg

最左边的图就是我刚刚描述的合理的空间关系,大家由于角色后面的地块模型非常高,所以说它的头是插在模型当中的。

有的同学可能会说,把这个角色调整到垂直场景不就解决问题了吗?那么我们最右边这张图就是把角色调整到垂直于场景,这个时候它和场景的关系对了,深度关系也对了,但是我们看起来非常奇怪,像纸片人。

这种情况下,如果我们调整一下摄像机的角度,比如像中间这张图一样,调整到能够正常地平视这个角色,那整个空间关系看起来是正确的,只是这样一来我们的游戏是没法玩的,因为摄像机只能以这个角度去看的话玩家是没法操作的。

为了解决这个问题,我们最后达到的效果是希望像左边这样,但是能解决穿模的问题。这其中曾经经历了一个错误的思路,也就是说我们渲染的时候关闭了一些Z-test,同时 Z-write 也不大,我们把整个场景中的模型、摆件和角色都进行了一个深度混排。我们手动对它排序,这类似于传统 2D 游戏的处理方式。

我们手动排序之后手动去归置,这样确实能达到相对比较正确的结果,但是会带来两个主要的问题。第一,我们会破坏这个合批,打破它静态的一个 batching(批处理),为什么?

因为我们整个场景是一个静态,包括它的光照贴图和阴影贴图,我们在渲染的时候可以用相当低的 DrawCall 做到所有的场景,绝大部分场景的DrawCall 都在个位数。如果需要混排,需要打乱角色前、角色后的顺序,我们会增加非常多的 DrawCall。

其次,我们会有一些小摆件,比如场景上的一些树木是跨两个格点的,这些小摆件我们大家对它进行排序就很难知道它到底在哪一层。

最后我们解决的思路是让角色需要看起来垂直于摄像机,但实际上它是垂直于场景的。我们解决方案实际上是把深度进行一个调整,在 Unity 当中摆位或者是把场景当中的位置和着色系它的角色都是垂直于摄像机的,也就是躺在场景上。

微信图片_20201123111433.jpg

而在 Vertex Shader 最后我们会把深度从刚刚那个空间变换到垂直于场景的空间,这样一来,对于深度测试和深度写入来说就好像角色是垂直于场景上的。

左边这张图就是一个正常的透视关系,也就是说角色是躺在场景上,会穿模的情况,实际上最后做深度测试的时候,我会把它角色的深度从刚刚左边这个图变换到右边这个深度空间当中,你可以看到整个角色现在是垂直于场景,并且被抽起来的,它变得更拉长了。

为什么?这张草稿能说明问题。

微信图片_20201123111458.jpg

首先,这个 Camera 是我们的事件方向,它和场景是有一个夹角的,角色垂直于这个 Camera 的方向,它的夹角和场景夹角是30度,这个时候我们可以做这样的一个三角形,而这个三角形的斜边就是我们箭头指的方向,就是我们在深度测试的时候实际上所在的位置。

可以发现,线上的每个点和原本角色上的每个点是一一对应的。这是一个直角的三角体,而且是一个30度夹角的,斜边和对边的比例是1:2,所以说实际上这个边的长度是它的2倍。

这里我不会深入一些处理的细节,因为我相信这个比较容易的,通过大家的计算都可以得到。只需要说一点,做这个变换只需要在 Vertex Shader 最后做一个深度变换。需要注意的是,这个时候 Vertex Shader 最后的位置实际上是处于透视除法之间起始空间当中的。

所以此时如果要做一个 Z 轴的变化,在起始空间中需要考虑到第四位 W 参与运算,这里是个简单的代码。

微信图片_20201123111452.jpg

那么问题解决了吗?其实并没有。我们在整个视觉方案当中还遇到了很多别的问题,刚刚提到的是其中最重要的点而已。这里图中说明的是另外一个问题。

微信图片_20201123111501.jpg

我们的干员重兵,他的攻击方式比较特别,往下挥鞭的时候纵深会特别长,所以说会直接穿到这个模型里面,如果我们把它的角色深度拉伸到垂直于场景,它依然会穿进去,所以此时我们做了一个特殊处理。

当它的高度大于等于0的部分,我们使用刚刚说的处理方式,而高度小的部分我们则使用另外一套处理方式,使这个鞭子被旋转到平行于这个场景的 X、Y 平面,这样才能在同样正确并且一致的条件下正确地绘制出来。

除了图纸之外,还有空中,它其实处理方式也是不太一样的。所以,这里是有很多细节的,如果大家感兴趣,接下来我们再详细探究。

第二个问题是 Lightmap 不一致的问题,而这个问题很多友商包括很多网友在网上也提到过,我也看到很多文章,他们会发现编辑器在实机,在移动平台上可能最后 Lightmap 的结果都不太一样。

微信图片_20201123111504.jpg

我们调研得到的结果是,如果抛开 Unity 版本谈这个问题是没什么意义的,因为每个 Unity 版本对于 Lightmap 编码解码的细节都有一定的调整。所以我们这里所有的结论是在2017年的 LTS 版本上。

这个问题的原因是因为光照贴图存储的并不是颜色。它和通常的图是不一样的,它存储的是一个间接光,它的范围是在0和1之外的,我们无法用一个常规的 LDR 的贴图格式把它存下来,它原本是一些 APBR 的信息。

所以说我们需要把它进行编码,才能重造一些 LBR 的贴图格式。那么这个编码的方式在不同平台上是不一样的,这个原因也导致了最后不同平台上的表现结果不一致。

大家可以看这两张图。在明暗交界的地方实际上那个阴影会泛蓝紫,这个蓝紫就是阴影的细节,在左边这张图是被吞掉了,这个细节是我们需要处理的。

微信图片_20201123111507.jpg

这里我不会详细地描述 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的方式。

微信图片_20201123111510.jpg

而在 double LDR 的方式下,alpha 会直接丢弃,这才是我们想通过做一些操作把一些信息存到 alpha 通道当中,你读不出来的是读不出来的,读出来的是个常量。

接下来是我们做测试的一些细节。

微信图片_20201123111513.jpg

就结论来说,如果我们继续保持 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 角色的渲染表现?这个问题实际上是一个比较复杂的问题,我们现在也在探索。

微信图片_20201123111516.jpg

我们总结了几点:

首先,我们会对每个主题的场景定义一套作用于所有单位、所有角色的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角色能融合得更好。

最后,我们提供了这么多的选项是让我们的美术工作人,也就是说我们的艺术家们来做最后的处理的。因为我相信技术人员只是提供工具,最后的整个画面效果肯定还是需要以更加感性的认识去调整的。

今天的分享就到此结束。谢谢大家。再见。