Unity3D之如何将包大小减少到极致

Unity3D之如何将包大小减少到极致,图片是游戏app里最最占空间的资源,所以请各位还没有理解u3d对图片文件存储方式理解的请看《unity3d-texture图片空间和内存占用分析》。因为u3d对资源的压缩并不阐述的十分详细,所以很多项目在遇到包大小瓶颈时非常头疼。我也不是神仙,也同样痛苦过,但经历几个项目的折腾,最终能梳理出一套能将u3d包大小减少到合理范围的方法。

首先来展示下,官方如何说的:(http://docs.unity3d.com/Manual/ReducingFilesize.html 官方手册)

1.替换jpg,使用psd,减少重复资源

2.剔除不必要的资源

3.打包时查看log纪录,由此判断需要减少的文件类型

4.优化,压缩图片,减少图片大小

5.优化,压缩网格和动画,减少文件大小

6.剔除system.dll和system.xml.dll ,尽量不要依赖他们,或用其他组件来代替。

这些官方解释对我们帮助甚少。

为了将包大小减少到极致,我把包分成三段:1.首包(里面包含了最最必要的资源)。2.首次进入包加载(加载游戏运行必要的资源)。3.游戏运行中资源加载(按每个游戏不同各自定义,以场景和单位个体为主要,在画面进入时加载资源,加载结束后再运行并显示)。

这个说的好笼统,来说的细点:

大部分网络游戏都可以把资源分成包内资源和首次进游戏加载的资源。这样就解决了一部分资源放里面的问题。

不是所有游戏都适合游戏进行中加载网络资源的,况且在中国网络环境这么糟糕的情况下。敢在游戏中加载网络资源的也就那些重度手游,而且是大厂的重度了。所以我们还需要想办法把前两种方法里的资源压缩到最小。

因为首包内大部分资源都是ui资源,以及一些必要的场景资源。所以我们最主要是提取这些资源到外面并放服务器上去。

一般包内资源操作都是阻塞式的,为了让游戏的架构没有太大的变化,我们还是使用阻塞加载方式,但方式稍微换一下,本来使用Resources.Load的接口,改用AssetBundle.CreateFromFile + AssetBundle.Load。把包内绝大部分ui以及其他资源打成一个assetbundle文件,并且使用的是非压缩模式。

因为非压缩模式使得文件更大,我们还需要一步操作,就是将文件压缩成zip文件后上传服务器。

我们将包外的资源压缩成zip文件。这样在加载网络资源时就能省去很多网络流量。下载下来后,对zip文件进行解压,后再对zip文件删除,减少空间占用。

这样做以后是不是差不多所有资源都在包外了。而且基本上包内就只有程序和游戏首画面的资源了。30mb内应该也可以轻松达到。

至于如何使用AssetBundle的这些接口,我对Assetbundle api做了一个封装。所有assetbundle的api都封装在里面。你自可以尽情使用。请看:Unity3DGameResource

关于u3d的AssetBundle资源加载与打包封装,请查看《unity3d之assetbundle资源加载封装》这篇文章。

下面说说关于动态资源加载和资源导入内存的所有方式,这是优化资源的必要条件,只有你知道了所有的加载和导入途径你才能对项目资源优化进行全面的分析。知道了有哪几条路你才能选择一条最好的。如下:

利用动态资源加载有几种方式:

1.将资源放入assetstream文件夹随打包一起打入文件。

2.将部分资源放在服务器,游戏前或游戏中进行加载,并保存到本地。

3.将资源压缩成多个zip文件放在服务器,客户端下载这些zip文件进行解压。

其实www.LoadFromCacheOrDownload加载机制也可以算一种,但似乎u3d4.5.2开始已经摒弃这个接口,大部分人也不太建议使用这个接口,似乎是因为这个界面消耗内存太厉害。其实具体什么原因我也不太清楚。个人认为这个接口太过死板,操作余地太小,受限太大。

资源导入内存的方式有几种:

1.从Resources文件夹中导入。这是阻塞加载最常见的方式,接口Resources.Load();

2.从某地址加载资源www。这是异步加载最常见方式,接口new www(path);

3.直接从文件或者bytes[]生成AssetBundl,接口:AssetBundle.CreateFromFile阻塞方法, AssetBundle.CreateFromMemory异步方法,AssetBundle.CreateFromMemoryImmediate阻塞方法

4.使用File类加载文件,File.ReadAllBytes,File.ReadAllText。

有了资源加载和内存导入后,还需要配备资源验证方式,这样整个项目动态加载体制才完善。资源版本更新方式可以使用json格式并以文件形式查看。验证方式的理解,还需要大家使用在项目里才能体会到真正的用途,才能将原理牢记于心。

验证资源版本有几种:

1.资源整体验证。步骤:1.客户端向服务器发送资源版本。2.服务器匹配最近版本号,若版本号不同,比较两个版本号之间的内容差异,发送差异资源地址。3.客户端删除差异内容中需要删除的文件资源,加载需要下载的文件资源并保存文件。最后保存版本号。

2.单个资源文件的时间戳验证。步骤:1.客户端向服务器发送资源版本号。2.服务器匹配最新版本号,如果不同就重新发送一份资源版本列表,里面包含了资源文件的时间戳。3.保存版本列表。4.在客户端需要加载该资源时比较时间戳是否一致,如果不一样或这不存在就加载资源文件并保存固定时间戳。

3.单个资源文件md5验证。步骤:1.客户端向服务器发送资源版本号。2.服务器匹配最新版本号,如果不同重新发送一分资源版本列表,里面包含了资源文件的md5码。3.客户端比较新旧资源版本列表中的,删除需要删除的和更新的资源。4.在客户端需要加载该资源时查看文件是否存在,如果存在就说明资源是最新的。如果不存在则需要实时下载。

对于资源版本验证与更新我写了一个关于资源更新的解决方案https://github.com/luzexi/version_update 是一个用php写的脚本,将资源进行记录,每次生成版本,对比资源是否有被修改,或删除,或增加,有兴趣可以看看。

转发请注明出处:http://www.luzexi.com

· Unity3D, 游戏架构, 前端技术

感谢您的耐心阅读

Thanks for your reading

  • 版权申明

    本文为博主原创文章,未经允许不得转载:

    Unity3D之如何将包大小减少到极致

    Copyright attention

    Please don't reprint without authorize.

  • 微信公众号,文章同步推送,致力于分享一个资深程序员在北上广深拼搏中对世界的理解

    QQ交流群: 777859752 (高级程序书友会)