<
Unity WebGL的内存优化方案
>
上一篇

C#通过命令行调用python脚本
下一篇

浅谈软件开发模式

前提

可能是受疫情影响,最近同事发布的WebGL也像缺了氧,疯狂报Out of Memory,生猛地干扰了预期进度。因此,我们整理了一份解决思路和方案,希望能帮到和我们一样在WebGL环境里摸爬滚打的人。

正文

一般在看到out of memory时,我们都能很直观的明白是内存爆了,需要降低内存消耗,但是,影响内存的点其实是繁杂的,真的进行优化工作时,往往又无从下手。

问题原因分析

很多Uni猿在运行WebGL报出out of memory时,第一反应都是自己的资源太大了,导致浏览器内存炸了,其实这个说法是模糊的。如果处理妥当,浏览器的内存占用,甚至可以达到硬件内存支持的上限。

Out of Memory这个错误,是因为瞬时加载的缓存超越了Unity为WebGL发布环境设定的上限,举个简单例子:吃饭时,有个人坐在你旁边,当你准备一口吃掉整碗米饭时,他就会拦住你,然后说:这样不行,你会噎住的。

根据上边这个例子推想,我们项目中出现“噎住”的时间节点,往往是在场景加载和大型逻辑执行的时候。

异步加载能否回天

场景加载这个问题,网上有人说可以用异步加载会更快,内存损耗会更少。对于此说法,我个人持否定观点。首先,众所周知WebGL环境里无法开多线程,那么所谓的异步加载,其实也是在Unity的主线程中开启一个协程进行,这在浏览器中,均是以浏览器内存形式被系统监控。异步加载的目的,是为了解决场景加载时间造成的“卡死”错觉,市面上多数Unity游戏都会有Loading界面,这其实就是因为现阶段场景资源过大,HDD已跟不上人们的心理预期(土豪都配全固态电脑呢),即使画面出现短暂1帧或2帧的卡顿,用户都会心生不爽,更别提加载场景时画面卡住几秒钟甚至几十秒了。

解决方案

优化资源

首先从美术资源下手,WebGL嵌在浏览器内,Unity很多功能是有针对性削减的,但项目中美术资源是否也如此呢?其实,大多数美术人员,往往更注重自己作品的效果,而非性能损耗,4k、8k贴图眼睛都不眨。针对这个问题,我们不能去直接限制其降低贴图质量,不然以后需要在PC端中使用高质量贴图,难不成让人家再还原回去么。在Unity中,选中Texture,Inspector面板最下方可以选择WebGL平台,勾选Override for WebGL,再将Max Size改到自身需求上限。

image-20200513103312381

如图,我自己需要的Max Size仅为1024,而测试后发现,2048和1024,理想情况是有着4倍差距的。

在这里,我们可以选用PackageManager里边的Memory Profiler,进一步剖析工程里各资源的内存占用。

image-20200513111628743

如图,Memory Profiler可以对资源内存占用进行监视,点击相应类型后,还能细化展开,查看每一个资源的内存情况。猿们可以根据捕捉到的名字,查找相应的资源,做出适合自己需求的优化处理。

image-20200513111825504

优化设计

有一句老话,上梁不正下梁歪,一个程序,如果从原型设计就有问题,那么后续再怎么从编程角度优化也无济于事。

大多数初级设计者,都有一种“我全都要”的心态,为了成绩,天马行空,要求程序小巧,流畅,内容多,画质高……这种设计往往是最令人头疼的,产出的基本都是怪胎或者死胎。

在拿到需求的时候,我们要根据核心目的,在最短时间分析出其设计的优势与劣势,并在两者间做权衡。

举一个实战例子:

我们拿到一份林地漫游的需求,真实地理面积给定,并存在树木密度下限要求。

这种情况下,我们会指定几种方案:

第一种,降低模型和贴图质量,满足场景规模需求。

第二种,维持模型和贴图质量,划定漫游范围,从而减小场景规模。

第三种,维持模型和贴图质量,根据性能损耗选定单位活动面积,并将真实地理面积划分成多个单元,利用AB加载和异步加载实现无缝漫游。

我相信更多的设计者倾向于第三种“两全其美”的方式,但这将带来更高的人力资金损耗以及更长的制作周期。当预算不够,且注重规模时,应选第一种;预算不够,且注重美观度时,应选第二种。

结尾

在面对Out of Memory时,不要轻易相信什么“这个平台只适合做xxx”的言论,平台只是一个载体,适不适合,是要看设计者和制作者而定的,裤子太紧穿不上,要么换一条,要么去减肥 : p

Top
Foot