zoukankan      html  css  js  c++  java
  • Unity资源Tree-资源加载

    1 基础API

    1.1AssetBundle.LoadFromFile(Async)

    LoadFromFile(Async)从本地存储(如硬盘或SD卡)加载未压缩或LZ4压缩格式的AssetBundle。API将只加载AssetBundle的头部,并将剩余的数据留在磁盘上。

    AssetBundle的Objects会按需加载,比如:加载方法(例如:AssetBundle.Load)被调用或其InstanceID被间接引用的时候。在这种情况下,不会消耗过多的内存。但在Editor环境下,API还是会把整个AssetBundle加载到内存中,就像读取磁盘上的字节和使用AssetBundle.LoadFromMemoryAsync一样。

    1.2 AssetBundle.LoadFromMemory(Async)

    LoadFromMemory(Async) 是从托管代码的字节数组里加载AssetBundle。也就是说你要提前用其它的方式将资源的二进制数组加入到内存中。然后该接口会将源数据从托管代码字节数组复制到新分配的、连续的本机内存块中。如果AssetBundle使用了LZMA压缩类型,它将在复制时解压AssetBundle。而未压缩和LZ4压缩类型的AssetBundle将逐字节的完整复制。

    此API消耗的最大内存量将至少是AssetBundle的两倍:本机内存中的一个副本,和LoadFromMemory(Async)从托管字节数组中复制的一个副本。

    1.3 AssetBundle.LoadFromStream(Async)

    LoadFromStream(Async)跟LoadFromFile通过filepath获得native stream,但区别就在于LoadFromFile内部经过封装能分段加载,而LoadFromStream的参数是一个托管的stream流,它会一次性将ab文件全部load进内存。

    1.4 UnityWebRequest

    request = UnityWebRequest.GetAssetBundle();
    AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
    
    //或者
    request = UnityWebRequestAssetBundle.GetAssetBundle();
    AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
    
    //或者
    request = UnityWebRequest.Get();
    byte[] datas = request.downloadHandler.data;
    save2File(datas);//如果有LZMA压缩需要解压然后再压缩为LZ4
    //也可以用Caching缓存 
    //或直接用CacheAssetBundle缓存,但要注意bundleName重复的问题
    

    2 实施加载

    2.1 更新资源

    更新asset资源,获取服务器信息比对,有差异获取需要更新的文件:依赖清单、下载清单。依赖清单可以是AssetBundleManifest清单或者自定义的依赖清单,每次打包该文件都会改变,必须要更新;同时它也记录了所有包的依赖。下载清单就是它记录每个需要下载的ab包信息。

    资源热更


    2.2 缓存资源

    Unity可以用两种缓存方式:

    第一种方式是用Unity封装好的Caching与UnityWebRequest.GetAssetBundle

    Cache newCache = Caching.AddCache(version);
    Caching.currentCacheForWriting = newCache;
    UnityWebRequestAssetBundle.GetAssetBundle(url, CachedAssetBundle, [crc]);
    //不加第二个参数CachedAssetBundle,就不会写入缓存
    //同时LZMA压缩会自动解压并压缩为LZ4

    缓存后的资源路径:persistentcubeMatf707096b238006af4f6898d647573409[数据]

    image:保存时的命名可以随便写自定义; image:包的hash image:_data是包数据

    当该资源包有增量更新时,会在同名目录下新建新的hash包目录保存_data:

    image, 4af开头就是最新的资源被保存了。

    第二种方式用stream流自定义保存路径和信息

    UnityWebRequest www = UnityWebRequest.Get(url);
    byte[] datas = www.downloadHandler.data;
    //然后开始操作datas
    //如果有涉及到压缩解压
    //stream流写入

    批注 2020-08-06 160131

    2.3 加载资源

    Unity官网对加载本地资源时推荐API用AssetBundle.LoadFromFile(Async)接口,不推荐用UnityWebRequest。

    加载流程

    缓存全局依赖信息,方便查询一个包的依赖。
    为每个AssetBundle创建一个加载器,记录它包信息、依赖信息、加载状态。
    加载队列不是一次全部加载,这里做了一个每帧最大加载个数,防止一次加载过多太卡。
    加载完成,它的依赖对象引用计数++,它自身被实例化时引用计数也要++; 同时从加载队列中移除,加入到已加载完成的列表。

    这里加载本地资源路径有两个:安装包路径、缓存路径(热更缓存)。

    2.4 卸载资源

    调用unload(false),会把包体的Serialize信息删除,但是内存中已加载的assets还存在,如果后续再次加载相同资源,内存中就会有两份。

    对于使用这个卸载,一般都是对于不常用的功能模块,比如玩了许久才会用到该功能后续也不会立马用到,那么就可以先Unload(false),退出时再调用Resource.UnloadUnusedAsset();

    调用unload(true),会把包体Serialize信息以及加载到内存的assets对象都要删除。调用之后,卸载的很干净,也是出现引用丢失的问题。再次加载时,游戏会卡顿:从磁盘加载Instantiate后,会实例化各assets对象,同时也会实例化scripAssets对象,然后执行所有的monoBehavior回调。

    频繁使用的功能,不要调用Unload,就让他呆在内存,加速游戏体验。在某个合适的时机再卸载。

    我也在想unload(false)后,能不能直接引用内存中的实例对象呢?我觉得不可能,加载克隆一个prefab,它的依赖资源(比如mesh、texture)都是在Unity黑盒内自动实例化的,很难追踪到那些依赖资源的实例对象。再说了,内存共享也会有大问题的!

    卸载资源

  • 相关阅读:
    asp.net MVC 3/4 equivalent to a response.filter
    Asp.net MVC Request Life Cycle
    无法完成你的itunes store 请求发生未知错误50
    苹果Mac OS X系统十三年视觉变化发展史
    authentication not supported Connect to TFS Git from Xamarin Studio (non-hosted, locally installed TFS 2013)
    iOS开发者帐号申请指南
    Apple Developer Registration and DUNS Number Not Accepted
    apple developer D-U-N-S® Number
    苹果企业开发者账号申请记录
    D-U-N-S申请流程
  • 原文地址:https://www.cnblogs.com/baolong-chen/p/13456205.html
Copyright © 2011-2022 走看看