Unity资源管理和策略

Unity资源管理和策略


前言

好久好久好久好久没有写博客了。为啥呢?原因很简单,一是忙,二是懒。

学习这种东西吧,学的时候头疼,谁不想舒舒服服的睡觉打游戏呢?所以真的需要逼自己。头疼是好事,头疼的时候说明你正在变强。

上次写博客还是刚入职没多久的时候,跟那个时候相比起来,现在的我变强了(也变秃了 —_—)。

但回头想想发现写博客确实是一种督促自己学习和总结回顾的好方法,就又给它捡回来了。

不管写的东西有没有人看对吧,反正我写了,我总结了,知识和收获就是我自己的了。

希望自己能继续坚持下去吧。



资源加载

Unity中资源加载管理说难也不难,说简单也不简单。

主要可以从一下几个点开展开说:

1、加载路径——从哪里加载资源。

2、加载方式——用什么方式加载资源。

3、资源管理——怎么合理的加载和卸载资源。

4、资源优化——怎么更高效地管理和使用资源。



1、加载路径

Unity加载资源的路径大致可以分为三种:Resources、AssetBundle和网络。(当然如果你硬要从本地某个路径下加载单个资源我也没话说…)

Resources

这是Unity最基本的资源加载方式了,一般初学者第一次接触的就是Resources下加载资源。

本质上,就是Unity不想让你过多的管理资源,所以搞了个Resources目录,它来帮你管理资源。你所需要用的就是它给你提供的资源加载接口,调就完事了。

Resources.Load(); # 这里只是简单地举个例子,具体用法请参考官方API

是不是听上去很方便很简单?确实是简单。

但是简单背后面临着一个问题:它是怎么管的?管得有我自己管得好吗?如果没有我自己管得好,那我为什么要它管呢?

Unity的Resources实际上就是一个巨大的AB包,它会把里面所有的资源都打在一个bundle里。如果到项目后期资源越来越多,这个托管给Unity的bundle就会越来越大。将这个bundle加载到内存的速度就会越来越慢。并且还非常不好维护和管理项目里的资源。

换一个角度思考,一个巨大的背包里面装满了物品。当你想取出某个东西的时候,第一步先得把背包里的所有东西倒在地上,东西越多,倒的时间也就越长;第二步得从这些东西中找到你要的那个东西,东西越多,找的时间也就越长。如果有一天你想稍微清理一下背包,分分类,是不是也感觉特别麻烦?


简单总结一下,

一、内存变得更加难以管理。

二、过渡使用会极大增加资源加载时长。

三、无法做到增量更新,不灵活。


这其实就是用Resources管理不好的地方。而且Unity官方也推荐我们使用AB包来管理资源。

当然,做一些小型项目或Demo的时候,Resources是非常方便且能大量节省开发时间的一种方式。


AssetBundle

AssetBundle俗称AB包,不知道概念的小伙伴可以去看一下我的这篇: Unity——浅谈AB包

AssetBundle assetBundle = AssetBundle.LoadFromFile("...");
assetBundle.LoadAsset(); # 这里只是简单地举个例子,具体用法请参考官方API

目前项目基本都是使用AB包来管理资源。

与上述的Resources相比,优势显而易见:方便、灵活。至于AB包一些其他的特点,在这里也不过多解释说明了,上面链接的文章内容里都有。

当然管理起来会更加的复杂,需要考虑到AB包之间依赖等各种各样的问题。一般项目底层框架都会有一个资源管理器来管理AB包的加载卸载和资源的加载卸载。这也就是这篇文章之后要说到的东西了。


网络

从网络加载资源这里不多说,主要思想就是从服务器下载二进制文件然后在内存中转成需要的资源格式。

WWW www; # 可以用WWW,具体用法请参考官方API
WebRequest webRequest; # 也可以用WWW,具体用法请参考官方API

可以是单个资源,也可以是某个AB包。

这里会涉及到一些热更新相关的东西。具体可以看热更新相关的文章。(以后补坑)



2、加载方式

一般AB包和资源的加载都会有同步和异步两种方式,以下是两种方式简单的区别:

同步加载异步加载
同一帧下加载资源多帧下加载资源
CPU全力加载资源,如果资源过于庞大,会游戏画面会直接卡住,但是加载总时间会缩短CPU非全力加载资源,不会产生画面卡死的问题,但加载总时间会增加(说实话,时间加不了多少
代码简单,调用加载即可代码复杂,需要考虑到各种情况,比如正在加载时的再次加载和突然卸载、加载依赖关系的先后顺序等各种问题
玩家的操作反馈不好玩家的操作反馈更好
无需考虑消息和资源的先后顺序需要考虑消息先到还是资源先加出来
无需考虑细分物体,反正一帧下加载完成,卡就完事了通常来说,为了加载更加流程,需要将物体细分成各个部分分批加载

对于玩家来说,异步加载绝对是提升游戏体验的第一选择。虽然很麻烦,但是为了把游戏做到极致,多写几十行代码又何尝不可呢?

3、资源管理

当我们知道如何去加载资源之后,接下来的一步就是需要知道如何去管理资源。

资源管理作为项目底层框架的一个重要模块,说难不难,说不难也有点小难。

第一步:划分资源

首先如何合理的将资源划分成多个AB包,是资源管理的第一步,也是非常重要的一步。

它决定着你AB包的数量和细粒度,对此需要采取不同的策略。

如果AB包数量多,每个AB包的内容少,那么加载同样多资源的总时间就会相对来说变长,但对于需要加载的AB包就更加灵活。

如果AB包的数量少,每个AB包的内容多,那么加载同样多资源的总时间肯定就会减少,但灵活度也就大打折扣。

怎么去理解这个灵活度呢?很简单,越灵活,热更新越方便,要加载的依赖AB包占内存也越小。

第二部:加载方式

划分完资源,打完AB包,接下来就是从AB包中取资源了。

如何取?之前提到过的,同步和异步两种方式。选一种合适自身项目的即可,当然两种都使也是可行的。

第三步:依赖管理

AB包最关键的一个东西就是依赖/引用。

当一个AB包内某个资源用到了另一个AB包内的某个资源时,这个AB包就会依赖/引用另一个AB包。

如果被依赖的AB包没有加载到内存中,那么Unity是无法将依赖它的资源成功加载出来的。表现情况就是某些资源加载完后出现丢图、丢材质、丢预制等等。

所以如何把被依赖的AB包先加载到内存中去,是资源管理器需要考虑到的一个非常重要的问题。


这里多说一句,对于没有打AB包的资源,如果被打了AB包的资源引用了,那么这个没有打AB包的资源就会被拷贝到引用到它的AB包中。如果有很多这样的这样,就会出现资源冗余的情况。

解决方案很简单,把一些被引用到的资源打成一个公共的AB包。搞定!


第四步:卸载时机

加载完了,该轮到卸载了。

卸载也是一个非常重要的环节,时机非常重要。

一个资源不用了,我是不是能够卸载它呢?

一个AB包没有被引用了,我是不是能够卸载它呢?

一个资源暂时不用了,但不久之后可能还会用到,我是不是能够卸载它呢?

一个资源不用了,但我不知道它之后会不会再用到,我是不是能够卸载它呢?

这些问题都是资源管理器需要考虑到的情况。

其实简单来说任何情况都可以卸载资源和AB包,大不了用到的时候再加回来,所以这只是一个策略的问题。如何将加载和卸载的时间和空间消耗做到最少,这才是卸载真正需要考虑的地方。



4、资源优化

在了解了上述资源管理相关的内容后,资源优化也不是个难事。

资源优化的方案有很多种,这里说一些比较简单又有效的。


对象池管理

试想,如果某个东西需要非常频繁的调用资源加载的接口,那么我们有必要每次调用都给它加载一次资源,并记一次引用计数嘛?

如果一个资源的引用计数过多,我们是否能保证它在调加载和卸载次数是一致的,从而使其能正常从内存中卸载呢?

如果答案是不能,那么就可以在资源管理器中添加一个对象池管理加载的资源。

策略很简单,对于频繁需要加载的对象,在加载完对象一次后就给它创建一个对象池。下次如果还需要加载该对象就不再调用资源加载接口了,转而使用对象池实例化一个对象出来返回给需要的地方。

这样的话,该资源的引用计数不会因为频繁地调用资源加载接口而疯涨,可以很方便地保证该资源在正确的时间进行了卸载。除此之外,这样也不需要重复地从把资源加载到内存中。


延时卸载

当你销毁了一个对象,并且没有别的地方引用该资源的时候,理论上它应该从内存中卸载掉。

但当刚卸载完后,你立马又需要创建该资源,怎么办?

延时卸载的好处就体现在这里了。

对于一些需要卸载的资源,可以设置一个延时卸载处理。比如30s后,确保短时间内不会再用到该资源后,再进行资源从内存中的释放。


预加载

对于一些必要的公共资源,为了让游戏或UI打开速度变快,我们可以使用预加载的策略。

比如在游戏的Loading界面提前将一些资源加载到内存中,加快之后使用的速度。

但是要注意的一点是,预加载的资源一般是不会主动去卸载的,所以作为一个空间换时间的策略,斟酌使用,不要一股脑全给预加载到内存中。


其他

还有一些资源优化的方案,像图集大小的优化之类的,方式无穷无尽。由于本人开发经验和技术能力有限,一些高深的优化方案也需要去多多学习。



后记

上述内容主要是一些在开发工作中遇到过的一些知识的总结。内容有限,自己也在不断地提升和学习。

在此进行一个总结和回顾,也希望能帮助到一些初入游戏开发行业的小伙伴(老资深程序员还需要看这个? —_—)。

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值