【厚积薄发】Addressable如何删除旧资源

1)Addressable如何删除旧资源
​2)Addressable如何更新Catalog文件
3)Editor在Android平台下加载AssetBundle的疑问
4)资源被打成AssetBundle后,图集被多次加载在内存中
5)Gfx.WaitForPresent耗时与GPU的关系


这是第209篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Addressable

Q1:目前计划使用Addressable来实现资源热更新,实际真机测试发现当资源更新后,旧的资源Addressable并不会把它删除,同时可以看到App占用的数据文件会越来越大。请问有什么办法可以把指定的Group或Label的资源删除吗?

试了Addressable.ClearDependencyCacheAsync也不行。实际测试这个接口只能删除最新版本的资源。当本地已经是最新版本资源时这个接口确实有效;但是如果本地需要更新资源时,这个接口应该也是尝试去删除最新资源,然而本地并没有最新版的资源,所以大概就无效了。

A:调用Addressable.ClearDependencyCacheAsync实质是调用了 “Caching.ClearAllCachedVersions();”。事实上是使用了Unity的Caching系统。

在Windows编辑器环境测试了一下。
Caching的目录为“C:\Users\UserName\AppData\LocalLow\Unity\ProjectFolder”,当正常下载AssetBundle以后,该目录内就出现 “stage01_298bd883434eedb69ea7316cb23e0b0d\662ab7a0d2aa99bc7a2dbb7baec63872” 之类的目录,并保存着当前的AssetBundle版本,当更新AssetBundle并执行下载以后,该目录也会出现其他AssetBundle的Caching目录。

在执行下载之前,先执行了一下“Caching.ClearCache();”,这时会发现Caching目录内已经被清空,所有版本的AssetBundle都没有了。下载完成后,该目录只保留了最新的AssetBundle资源。由此可推,即使不通过Addressable系统,仍然可以通过Caching把所有的资源都清理掉。

于是继续进行第二个实验,连续更新几次AssetBundle以后,Caching目录内已经有多个版本的AssetBundle目录了,当有新的更新后执行 “Addressables.ClearDependencyCacheAsync(key);”,发现的确并没有将旧版本的AssetBundle都删除。因为“Caching.ClearAllCachedVersions”的参数是对应的AssetBundle名字,而Addressables的管理AssetBundle包名是带Hash的,因为每个版本的AssetBundle文件名都不一样的,Caching系统也就无法分辨了。

继续做实验,将打包名字去掉Hash,Caching目录内的AssetBundle目录名也不带Hash了,然后连续更新几个版本后发现,该AssetBundle目录内多了几个不同Hash版本的目录,内部才是真正的AssetBundle。于是走“Addressables.ClearDependencyCacheAsync(key)”,这时就能正确地删除旧版本,然后再更新新版本了。

Q2:确实不勾选Hash打包可以成功删除了,这种方式貌似就是覆盖式的打包,不知道会不会有其他隐患,目前来看够用。

A:隐患就是如果按照Label来做更新检查,本来可以只下载差异部分,但是因为同样使用Label做清除Caching的工作就会造成重复下载原本不必要更新的部分。于是就需要遍历所有的Location然后去检查更新,并将有更新的AssetBundle放入列表,然后再依次清除旧缓存,重新下载。这样就和传统方案没太大区别了。

Q3:请问下不勾选Hash其实就不用清除了吧?名字一样不是会直接覆盖吗?

A:不勾选Hash,只是在Cache的目录内第一级资源同名子目录是一致的,但是里面保存具体数据的子目录是递增的,因为有不同版本。每个版本都会有一个子目录。这个是Caching系统管理的。

感谢黄程@UWA问答社区提供了回答


Addressable

Q:项目使用Addressable做资源管理,资源更新方面因为原来有一套下载更新流程,就不使用Remote功能,全部Group都是cannot change post release。只是单纯用Addressable打包,然后比较差异下载回本地,使用“Addressables.InternalIdTransformFunc”指向新资源的路径。

但是由于下载回来新的Bundle的crc跟原始Catalog的crc不一致,会报错“CRC Mismatch. Provided 16302c0b, calculated 17167beb from data. Will not load AssetBundle”。

希望在下载完资源后重新加载新的Catalog文件,应该怎么实现?尝试使用了“Addressables.LoadContentCatalogAsync”接口加载下载回来的Catalog文件,但是还是报错。

A:使用“Addressables.LoadContentCatalogAsync”后还是出错的可能性有一种:因为默认的Catalog对应的Locator并没有移除,造成查找时首先在默认的Locator内找到资源,而因为不走Addressable的更新流程,那么默认的Locator对应的crc永远就是旧的,于是出错了。

感谢黄程@UWA问答社区提供了回答


Rendering

Q:Unity Editor下加载AssetBundle,材质球Keywords正常,但是某些属性不存在。
Unity 2018.4.23f1 Android版本,Shader用的是新建的SurfaceShader,Shader Stripping设置如下图。

Mat、Shader、Prefab打在同一个Assetbundle上,在Editor中运行加载该Assetbundle上的Prefab,会发现一些属性不存在,而原本挂在这个场景中的Prefab,则是正常。

【厚积薄发】Addressable如何删除旧资源_第1张图片

【厚积薄发】Addressable如何删除旧资源_第2张图片

【厚积薄发】Addressable如何删除旧资源_第3张图片

【厚积薄发】Addressable如何删除旧资源_第4张图片

A:打包成APK后连接FrameDebugger看到在场景中的球和AssetBundle加载后实例化的球的Shader参数信息完全是一样的,所以可能是在Android平台Build后的AssetBundle在Editor中加载才会出现楼主所说的问题。

【厚积薄发】Addressable如何删除旧资源_第5张图片

【厚积薄发】Addressable如何删除旧资源_第6张图片

【厚积薄发】Addressable如何删除旧资源_第7张图片

另外再做了一个对比试验,将平台切换成PC。在编辑器里,场景中原有的球和AssetBundle加载出来的球的渲染就是完全一样的了。

【厚积薄发】Addressable如何删除旧资源_第8张图片

【厚积薄发】Addressable如何删除旧资源_第9张图片

感谢Xuan@UWA问答社区提供了回答


AssetBundle

Q:资源被打成AssetBundle以后,发现图集被多次加载在内存中,这正常吗?

【厚积薄发】Addressable如何删除旧资源_第10张图片

若是不正常,是什么原因造成这个问题的呢?怎么解决?(Unity版本是2017.3.9)

A1:可能是在通过AssetBundle.Unload(false)卸载AssetBundle对象后,重新创建该AssetBundle对象并加载之前加载过的资源到内存,这样就出现了冗余。还有一种就是打包时出现了冗余。

感谢李星@UWA问答社区提供了回答

A2:根据经验说说造成这种情况的原因。

  1. 确认打包的时候,图集是依赖的打包,而没有被打包到各个prefab里面。这个推荐使用UWA的在线AssetBundle资源检测工具,直接把整个项目的AssetBundle上传,可以查出很多问题。
  2. 你把Assetbundle包给卸载了。AssetBundle.Unload(false),这样Assetbundle关联断了,就会重新加载资源,如果楼主用的是LZ4的压缩格式,不推荐再去调用Unload(false)了,第一LZ4的ab包本身占用极少的内存,第二Unload(false)的资源多了,调用Resources.UnloadUnusedAssets接口,容易造成卡顿。应该自己写引用AssetBundle计数,直接Unload(true)。

感谢简单就好@UWA问答社区提供了回答

A3:根据经验有以下几点供参考。

  1. 使用Unload(true) 更好一些。经常会有人操作不规范挂住一些资源,然后越积累越多,主动释放安全很多。
  2. Unload(false) 会导致再次加载同一资源被开一个新的区域。某些重复利用率较高的资源,会出问题。比如,材质A和材质B都引用一个贴图,加载材质A根据依赖加载贴图,然后释放AssetBundle;加载材质B时,会加载第二份贴图。所以用Unload(false) 并不能达到及时释放ab的效果。
  3. 反复加载的问题。卸载AssetBundle之后,再次使用尚未析构的资源,又需要重新加载AssetBundle,虽然LZ4的加载速度可以忽略不计。

感谢欧月松@UWA问答社区提供了回答


Rendering

Q:请教一下,在报告中看到Gfx.WaitForPresent很高,是不是就说明GPU压力很大?CPU均值在19ms左右,是不是说明压力在GPU端而不是CPU?是否应该先去优化GPU?

【厚积薄发】Addressable如何删除旧资源_第11张图片

A1:Gfx.WaitForPresent的值高一般是开了多线程渲染,要么在做垂直同步,要么GPU负担较重,CPU已经做完了等着GPU完成做呈现。建议查一下具体渲染的内容,或者在Profile内看看渲染线程的工作情况。

参考文章:《扒一扒Profiler中这几个“占坑鬼”》

感谢黄程@UWA问答社区提供了回答

A2:Gfx.WaitForPresent就是GPU瓶颈:

  1. 降分辨率;
  2. Shader优化,优化指令,高中低配使用不同的Shader LOD;
  3. 做视距控制,不光减DrawCall,不透明物体同样存在Overdraw,特别是场景复杂度高的情况下。

感谢BQ哥@UWA问答社区提供了回答

封面图来源于网络


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)

你可能感兴趣的:(问答,资源,rendering)