美文网首页
AssetBundle异步加载资源阻塞主线程的疑问

AssetBundle异步加载资源阻塞主线程的疑问

作者: 侑虎科技 | 来源:发表于2020-04-02 18:01 被阅读0次

    1)AssetBundle异步加载资源阻塞主线程的疑问
    2)Memory Profiler中ShaderLab占用内存大
    3)关于C#垃圾回收的问题
    4)RenderTexture占用内存过高
    5)Unity 2018.4.17f1异步加载AssetBundle


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

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


    AssetBundle

    Q:请问AssetBundle.LoadAssetAsync()这个真的是异步获取资源吗?我用的是个人版Unity,这个API会阻塞主线程,是不是需要专业版才行呢?

    A:AssetBundle.LoadAssetAsync()在加载资源的时候,比如Prefab,它里面用到的各种Texture、Mesh以及Shader都会在子线程Worker线程中进行加载。但是加载完成后会有后处理,比如Shader.Parse是一定会在主线程处理的,Texture和Mesh需要上传到GPU。如果开了多线程渲染并使用AUP功能,非RW的Texture和Mesh的上传会在渲染线程处理;如果没开多线程渲染,那么这一部分还是会由主线程来完成。这些后处理的名字叫XXX.AwakeFromLoad,如Texture.AwakeFromLoad,当主线程触发这些回调的时候,主线程其它的Update操作就必须等这些后处理完成才能继续。

    还有其它的像Prefab的序列化,各种Component的序列化等也都是在主线程完成的。所以一次AssetBundle.LoadAssetAsync操作,其实并不是完全的异步,主线程中依然是要做不少工作。具体细节可以观看UWA DAY 2019年的视频,里面的讲解非常清晰:https://edu.uwa4d.com/course-intro/1/91

    感谢Xuan@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5e7d54c386713137aaa097c1


    Memory

    Q:在真机测试环境下的Profiler里查看Memory使用情况,发现ShaderLab一项占用内存很大,里面主要是什么?

    在减少了Shader的变体后这部分内存有所下降 ,没有使用Unity内置的Standard Shader。有没有办法在不减少变体的情况下减少这一块占用的内存?

    另外,发现同一项下的Objects也占用很大。

    A1:ShaderLab是项目在编译Shader时产生的解析Buffer,其内存增长的特点就是Key words越多、变体越多,其内存占用越大。目前,还没有看到在不减少变体的情况下,可以减少该内存占用的有效方法。如后续有找到,我们也会来及时更新这块的内容。

    97MB过大了,18.9MB其实也较大,但可以接受。至于Objects,建议搜索题库,来查找之前相应的回答,比如:
    https://answer.uwa4d.com/search/objects
    该回答由UWA提供

    A2:这个过大是因为某个Shader的Multiple Compile太多导致的,Multiple Compile不会进行Shader裁剪,例如Unity的一个package,Post Process的Uber Shader就是个典型,我把里边的Multiple Compile都换成Shader Feature,然后用Shader Variant Collection只定义需要的分支,一个Uber Shader的内存占用从 30m直接降到忽略不计。但用Shader Feature一定要注意裁剪引起的问题,做好预处理。

    感谢bainan@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5a4d8df42b7c402cc97294a3


    Mono

    Q:一个开发中遇到的问题,请教一下,我在游戏一开始有个Zip解压资源的操作(大概150MB左右的Zip包,另开一个线程,非异步操作),解压完之后大概产生了200MB左右的GC Alloc,结束后不手动调用GC,游戏经过更新场景->登录场景->创角场景->主地图场景(在创角场景到主地图之间有手动调用GC),进入主地图后PSS内存大概550MB左右,在Profiler里看Mono内存,之前解压产生200MB没有回收,且后续游戏一直没有回收(每个地图之间切换也有手动GC,但也没有回收)。

    如果我在解压完之后,短时间内手动调用GC是可以回收的,Profiler里面的Mono内存回落了,这种情况下进入主地图PSS只有400MB多一点。总的来说,如果我不及时手动调用GC,解压产生的GC Alloc就会没办法回收,从而常驻内存,这是什么原因呢?

    A:Unity用的bdwgc不支持内存移动,猜测是你后续内存分配比较小,填充了之前解压产生的空隙部分,造成了碎片化,导致这些块无法归还操作系统。200MB的GC Alloc过高,建议拿C/C++重写一下。

    感谢littlesome@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5e787da918502d37b0fc2545


    RenderTexture

    Q:运行后,就会出现红框里的一些RenderTexture,但是游戏代码里所有的new RenderTexture都打Log,发现都没有执行到。请问,这些RenderTexture可能在什么地方创建呢?该如何优化呢?

    A:你这是在编辑器里看到的,真机不会有SceneViewRT这些,_TargetPool这些应该是由于使用了PostProcessing这类后处理组件产生的。

    感谢李星@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5dafd068efeb9d3d55d15b2d


    Editor

    Q:为了试试嵌套Prefab,把工程从2017升到2018,然后Windows Editor下就出现奇怪的AssetBundle.LoadAssetAsync载入资源不回调的问题,与此同时,使用LoadAsset同步加载是没有问题的(真机环境未测试)。

    尝试了调整QualitySettings.asyncUploadTimeSlice增加时间片及QualitySettings.asyncUploadBufferSize增加内存,均不起作用。随机出现部分资源载不到的问题。但是在PlayMode下,Editor中随机打开关闭一些界面(非游戏界面,Editor界面),会触发异步加载的完成回调,目前暂时找不到规律。

    A:在Unity 2018.4.18f1的Release Notes中找到一句话:
    Asset Pipeline: Fixed an issue where asset bundles could fail to load when using async loading methods. (1215446)

    发现是版本问题,将版本升级到Unity 2018.4.19f1后,此问题不再出现。

    感谢题主王啸予@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5e7c7ba118502d37b0fc2625


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

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

    相关文章

      网友评论

          本文标题:AssetBundle异步加载资源阻塞主线程的疑问

          本文链接:https://www.haomeiwen.com/subject/vdlouhtx.html