当前位置:   article > 正文

Unity资源加载方式以及管理_unity loadfromfileasync

unity loadfromfileasync

资源加载接口以及分析

一、

AssetBundle.LoadFromFile (string path, uint crc, ulong offset); 同步方法
AssetBundle.LoadFromFileAsync (string path, uint crc, ulong offset); 异步方法

最快的ab包加载方式,内存占用低,不可自定义硬盘数据格式

优点: 加载效率高,内存占用低,加载时只加载文件头,只有在真正加载对应资源的时候才会加载进内存

缺点: 指定的ab包必须是未经自压缩与加密的

使用指导: 虽然ab包加载的时候必须是未经自压缩的,但是我们可以在打包的时候自己压缩,占用包体大小变小,下载后解压到SD卡,存储的资源对象由于未压缩和加密可能被第三方盗用

二、

AssetBundle.LoadFromMemory (byte[] binary, uint crc); 同步方法
AssetBundle.LoadFromMemoryAsync (byte[] binary, uint crc); 异步方法

加载速度慢,内存占用高,可自定义数据存储格式

优点: 可实现自压缩与加密,自定义程度高

缺点: 必须将指定的ab包字节全部读入内存,内存占用高,加载速度慢

使用指导: 商业性质的项目,可实现对ab包资源存储格式实现任意处理,只需要在加载的时候把指定资源读入内存即可

三、

AssetBundle.LoadFromStream (Stream stream, uint crc, uint managedReadBufferSize); 同步方法
AssetBundle.LoadFromStreamAsync (Stream stream, uint crc, uint managedReadBufferSize); 异步方法

自定义程度高,内存占用低,加载方式的流实现

优点: 自定义程度最高,内存占用低,可实现自压缩与加密,从内存中读取,可将文件存储时切割为任意格式多文件,加载时,合并为一个文件流提供给API使用,可自己控制加载时数据缓冲池的大小,控制IO次数以及内存占用

缺点: 操作系统对打开文件数量有限制,使用时需要考虑使用场景

使用指导: 可拓展性最强的接口,可挂载对应的文件系统,对项目实现任意的资源自定义格式,文件细粒度划分,实现资源的压缩与加密,可自己设置数据缓冲池大小,由于文件打开数据限制需要具体项目进行测试

四、

UnityWebRequest 异步方法

远程下载任意格式资源

优点: 不占用包体大小,可实现远程实时加载资源,

缺点: 加载资源缓慢,需要对额外下载到本地的资源进行管理

使用指导: 通常在热更新时使用下载ab包以及文件清单,进行版本管理,游戏进行时,可以对按需下载的额外资源,进行下载以及后续管理,常用的如icon图片,人物原画以及额外模块,关卡。

资源加载以及管理(框架实践)

如果我们要实现一个资源管理的话,需要思考一下通过什么方式来实现,资源加载其实类似一个web请求,我请求加载一个资源,他返回给我一个Result,Result就是我们加载好的资源,那首先我们就需要一个加载器Loader的实现,然后再对我们加载好的资源进行管理,但其实这个加载器和资源是一对一绑定关系的,一个资源加载请求对应一个资源,并有对应的URL作为管理的key,我们可以通过管理这个加载器的Result就可以管理对应资源的Load与Unload。那么我们现在有了一个Loader的概念,现在要对其进行管理。然后我们再思考一下这个资源有什么特征,很显然,ab包是一个集合,而且在游戏中的各种资源对象,预设,贴图等等都是可复用的,那我们这个ab包应该也是一个可复用对象,我们可不希望,每次使用完他以后就进行手动释放,这样你还需要关心游戏中实例对象对于这个ab包的引用,这时候我们就引入一个池Pool的概念,我们希望这个池有着自己的管理策略,上层开发者并不需要知道这么多加载和释放的细节。那么对于这个管理逻辑,最核心的是什么呢,思考一下。游戏中我们需要用的实例对象关心资源的加载释放状态,资源对象需要关心是否有实例对象使用了我这个资源,那么他们之间存在了一个互相关心的状态,我们可以通过引用的方式来实现这种关心状态,并且ab包对ab包也是有依赖关系的,当我们通过Loader加载出原始资源ab包后,我们需要从ab包中加载出我们所需要的GameObject,Material,各种游戏的复合的序列化对象。他们之间就产生了引用关系但是他们身上还引用着其他ab包的资源对象,这时候就需要先加载其他ab包,那么ab包与ab包之间的引用关系就产生了,所以不管是加载什么物体,他们都存在一个引用被引用的状态。细心的小伙伴看到这里会发现这些资源对象ab包,贴图,材质,游戏序列化对象都存在一个加载的过程,还有一个引用和被引用的关系,那么我们其实可以统一抽象成一个Loader对象,上面都带着引用和被引用的对象。我们通过管理好Loader中的引用就可以保证游戏中的贴图,材质,模型,预设可以正确的显示,而上层开发者不需要知道资源何时被加载释放,实现一个自我管理。管理策略的核心就是当这个资源被引用的计数为0时,或者显式的调用强制释放时,资源是可以释放的。对于上层开发者来说,我需要获取一个需要使用的资源,那么他需要传入一个唯的key,** ab包名:资源名:资源类型**,就可以确定一个资源路径,那么这个唯一路径可以作为一个URL,传给loader,loader再解析这个路径,调用其他的loader加载依赖资源,并记录引用关系


功能模块划分

Loader: 用于创建资源加载的链接,获取当前加载状态,加载完的资源

LoaderPool: 用于管理Loader的对象池,实现池的管理策略可以管理Loader对象的gc以及资源的加载与释放

接口设计

  • Loader

    • Start() 开始加载

    • Uri 唯一路径

    • Error 错误信息

    • IsDone 是否加载完成

    • Progress 加载进度

    • Result 加载结果

    • IsResurrected 是否不在池中且没有开始加载

    • RefCount 被引用计数

    • Dispose() 释放加载器

  • LoaderPool

    • Initialize() 初始化加载器对象池

    • Get() 获取加载器

    • Put() 收回加载器

    • UnLoadAll() 强制回收所有加载器以及释放资源

    • Strategy 加载器池管理策略

框架实现思路以及细节

具体加载器需实现这个接口,统一由一个LoaderPool进行管理,先初始化好加载器对象池,当有人从对象池中拿出加载器使用Uri进行加载时,我们让加载器的被引用计数加1,当加载器需要加载依赖资源的时候,又从这个池中拿出一个加载器,此资源加载器引用也被加1,当调用Put()回收时资源加载器被引用减1管理策略: 遍历池中所有的加载器,如果被引用计数为0,且没有标记为为常驻资源时,可以释放此加载器以及资源。但有人肯定会说,如果有人拿出了这个加载器但是没有调用Start()加载资源怎么办,如果有人占着茅坑不拉屎,我们就在UnLoadAll的的时候打日志提醒一下这个同志,求求你快点使用这个加载器吧,或者放回池中,一直拿着要内存泄露啦。

结语

觉得我说的有用的话就在我的>>>>>戳这里 github项目<<<<<点上一个小小的star吧,咖啡就不用请我喝了,屑屑(比心)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/108113
推荐阅读
相关标签
  

闽ICP备14008679号