乐趣区

关于build:ShaderLab占用疑问

1)ShaderLab 占用疑难
​2)对于 Android 下 ARM64 和 ARMV7 的问题
3)对于 ILRuntime 相干的性能检测工具
4)字体加载问题
5)LZ4 压缩模式下的资源打包


这是第 239 篇 UWA 技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫 10 分钟,认真读完必有播种。

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

Shader

Q:我从官网下载了一份内置 Shader,本人写工具刷了一遍,确认界面外面材质球曾经没有援用内置 Shader,并且把 Standard Shader 都革除了,从内存去看也没有这个,然而 ShaderLab 的占用还是有点大,当初在主场景有 47MB。

A1:变体太多就会这样,认真看看那些很多关键字的 Shader。

感激 deviljz@UWA 问答社区提供了答复

A2:楼上说的对,分享一段几年前写的扫描工程 Shader 变体的代码,扫描一下,把 Top 前几的 Shader 改改就能降很多了。

[MenuItem("Find/GetAllShaderVariantCount", false, 20)]
    public static void GetAllShaderVariantCount()
    {
        #if UNITY_5_6
        Assembly asm = Assembly.LoadFile(@"D:Program FilesUnity_5.6.5f1EditorDataManagedUnityEditor.dll");
        System.Type t2 = asm.GetType("UnityEditor.ShaderUtil");
        MethodInfo method = t2.GetMethod("GetComboCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
        #elif UNITY_2017_1_OR_NEWER
        Assembly asm = Assembly.LoadFile(@"D:Program FilesUnity_2018.3.0f2EditorDataManagedUnityEditor.dll");
        System.Type t2 = asm.GetType("UnityEditor.ShaderUtil");
        MethodInfo method = t2.GetMethod("GetVariantCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
        #endif
        var shaderList = AssetDatabase.FindAssets("t:Shader");

        var output = System.Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory);
        string pathF = string.Format("{0}/ShaderVariantCount.csv", output);
        FileStream fs = new FileStream(pathF, FileMode.Create, FileAccess.Write);
        StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

        EditorUtility.DisplayProgressBar("写统计文件", "正在写入统计文件中...", 0f);
        int ix = 0;
        sw.WriteLine("ShaderFile,VariantCount");
        foreach (var i in shaderList)
        {EditorUtility.DisplayProgressBar("写统计文件", "正在写入统计文件中...", 1f * ix / shaderList.Length);
            var path = AssetDatabase.GUIDToAssetPath(i);
            Shader s = (Shader)AssetDatabase.LoadAssetAtPath(path,typeof(Shader));
            var variantCount = method.Invoke(null,new System.Object[]{s,true});

            sw.WriteLine(path + ","+variantCount.ToString());
            ++ix;
        }
        EditorUtility.ClearProgressBar();   // 革除进度条
        sw.Close();
        fs.Close();} 

感激李星 @UWA 问答社区提供了答复

A3:URP 有一套变体裁剪代码,拿来改改,退出你的打包流程会裁剪掉没用的变体(我预计你很多关键字用不到,所以应该会减不少)。

感激 Robot.Huang@UWA 问答社区提供了答复

A4:举荐应用 UWA 的本地资源检测,看下哪个 Shader 的变体多,是不是变体的问题,另外再确认一下是不是还有 Shader 的冗余。

感激芭妮妮 @UWA 问答社区提供了答复

Build

Q:对于 Android 下 ARM64 和 ARMV7 的问题,从教训上讲,同一个 Unity 的游戏在这两个架构下会呈现运行效率的差别吗?渲染效率会受到 CPU 架构的影响吗?

A:ARM64 能解决很多因地址空间有余、内存调配时呈现地址抵触而导致的内存调配失败的问题。比拟典型的就是高通的 Adreno 显存有余,或者说字典这种容器类型大量应用导致的内存泄露问题。然而,随同着的问题也就来了,同样的包 64 位比 32 位要大,对于对内存有严格要求的游戏,原本优化内存就曾经够头疼了,换成 64 位忽然又涨了一截,一股苍白无力感又油然而生。至于效率问题,没测试过也没比照过,楼主能够测测 FPS、温度、能耗等有多大区别。

感激李星 @UWA 问答社区提供了答复

ILRuntime

Q:UWA 曾经出了针对 Lua 的性能剖析,求 ILRuntime,新我的项目打算改用 ILRuntime,看中 Await 和 Async 来实现网络通讯的“同步”代码,战斗局部的逻辑代码也打算在 ILRuntime 中实现(强 CPU 计算会尽量用 C#实现),然而性能方面略有放心。若有性能剖析工具特地是与 C# 互相交互局部,能够在初期定技术框架给本人一颗定心丸就好了。

另外,请问 ILRuntime 曾经有哪些项目在线上胜利利用吗?再就是稳定性方面能接过 Lua 的拉力棒担当重任吗?

A1:根本满足日常须要。其实底层机制还是与 Lua 相似的,开发习惯和语言上会难受不少。作为功能模块附加或者热更新性能还是很不错的。不过性能方面没有十分针对性地去做测试,目前只能说满足我的项目须要。高计算量解决方面还是不倡议在 ILRuntime 做太多,根底起因其实跟 Lua 问题还是蛮相似的。

应用上来说,要留神 Adaptor 的定义。还有热更新方面,不同代码节点可能是须要别离出 ILRuntime 的热更包。这个在出包治理上会繁缛一些,不过开发语言对立上还是有不少益处的。

感激阿里 @UWA 问答社区提供了答复

A2:性能方面其实不须要太大的放心,分享一下我的教训:

  1. 肯定要用 Release 形式去编译 DLL,并且关上 DISABLE_ILRUNTIME_DEBUG 的宏;
  2. 因为解译执行,所以执行效率跟间接执行人造就有 20-100 倍的差距,太简单的计算必定不行;
  3. 运行时也是纯 C# 的,所以用 UWA 工具就能检测出一些性能问题;
  4. 咱们我的项目安卓用的有原生 DLL 效率必定是比 Lua 要快的,iOS 下面测试下来比 Lua 要慢一点,然而苹果设施以及 IL2CPP 的性能都不错,所以也能做到跑满帧;
  5. 对对象中的构造体赋值会有无奈防止的 GC,倡议先转老本地变量,或者 V3 这种间接存成 XYZ;
  6. Foreach 会产生 GC,写的时候不要用。

感激萧小俊 @UWA 问答社区提供了答复

A3:常识搬运工芭妮现身,搬于某国内新一线大厂的大柴:
有敌人用这个做上线了还行,计算密集型不能胜任,计算密集型能够用 Lua,双热更外围也是个值得参考的点子。

  1. 外围代码用 C#,例如:物理系统模拟之于闪暖。
  2. 战斗库逻辑层用 Lua,例如:秒算战报的回合制的战斗核。
  3. 业务逻辑用 ILRuntime,例如:配备零碎,升阶升星强化转生。
  4. 再套一层 Injectfix,修非 Burst 的 C#。

感激芭妮妮 @UWA 问答社区提供了答复

A4:因为 ILRuntime 是 C# 实现的,所以间接看 Profiler 就能看性能耗费。

感激终极大菜狗 @UWA 问答社区提供了答复

Resource

Q:我当初真机测试,在内存发现有两份字体的加载,一份是比方登录界面,或者其余自身有字体的场景援用到的,援用的是原始的 Font,另一份我发现是因为预制体加载到场景,会援用一份复制进去的字体。这个要怎么解决?

A:如果预设体是从 AssetBundle 中加载的,场景却不是 AssetBundle 加载的,那么必定是会有两份的,因为一般的场景打包和 AssetBundle 走的是不同的路线,是援用不到同一份字体资源的,一份是来自场景的 Sharedassets,一份是来自 AssetBundle。所以要么场景也走 AssetBundle 打包,要么场景中的用到这个字体的 UI 局部从 AssetBundle 动静加载。

感激 Xuan@UWA 问答社区提供了答复

Addressable

Q:LZ4 压缩模式下,Addressables 加载 Bundle 只会加载 Headers 到内存中,那么是否能够将所有资源打包成一个 Bundle?这样就能够不必思考资源粒度以及资源重复打包的问题了?

A1:如果是文件级别的资源更新,并且 AssetBundle 很大的状况下和从新下载整包没什么太大区别,资源粒度次要是为了不便缩小更新资源量。

感激郑骁 @UWA 问答社区提供了答复

A2:说一下我的整体思路,请大佬看看有没有什么隐患。

所有资源应用 Addressable 打成一个 Bundle 包,固定读取门路为 UnityEngine.Application.persistentDataPath,即永远读取本地。舍弃边玩边下这个模式,理论体验起来,边玩边下会导致频繁的卡顿,体验很不好。

首包公布一个小包,游戏启动时查看资源更新,资源 Bundle(包含后续的增量包)通过 C# 的 HttpWebRequest 下载(本人治理下载),反对断点续传,对立下载到 persistentDataPath,下载实现后正式进入游戏流程。

长处:

  1. 资源管理简略。
  2. 不必思考资源拆分粒度。
  3. 不必思考资源重复打包。
  4. 不必思考首次启动下载太多 Bundle 包导致的下载速度迟缓的问题。

毛病:
目前没想到有什么隐患,请大家帮忙斧正。

感激题主 ShiltonLi@UWA 问答社区提供了答复

A3:从资源卸载的角度来说这样做是不太正当的。Addressable 是通援用计数来解决卸载的,只有当 AssetBundle 的援用计数缩小到 0 的时候才会触发,触发时会调用 AssetBundle.Unload(true)。所以如果这个大的 AssetBundle 外面有一个资源须要始终常驻内存,就阐明那个 AssetBundle 也须要常驻内存,那么其它用不到的资源,如某张短时间应用过后就能够卸载的纹理,就卸载不掉了。当然这个说法的前提是用 Addressable 的加载接口和卸载接口来加载卸载资源。

感激 Xuan@UWA 问答社区提供了答复

封面图起源:Unity Shader Sketches
https://lab.uwa4d.com/lab/5b564b46d7f10a201fd903de
应用 ShaderLab 绘制草图。


明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在 UWA 问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。

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

退出移动版