Shared UI Mesh内存占用过高

Shared UI Mesh内存占用过高

1)Shared UI Mesh 内存占用过高
​2)GPU Skinning有办法实现阴影的做法吗
3)在真机上特效不跟着Spine运动
4)复制AnimatorController无效问题
5)Profiler中的System.ExecutableAndDlls如何优化占用


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

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

UGUI

Q1:缓存池中的UI如果不隐藏,Shared UI Mesh会比较高;如果隐藏,Shared UI Mesh会比较低,但是UI SetActive又有性能消耗,该如何权衡呢?

隐藏缓存池中的UI时,Shared UI Mesh内存占用:

不隐藏缓存池UI时,Shared UI Mesh内存占用:

A1:如果只有SetActive才能降低Shared UI Mesh,好像就没有其他选择了;但是如果切换layer可以降低,可以选择该办法。

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

A2:Shared UI Mesh是源自UGUI框架中的一个静态全局变量Graphic.workerMesh:

而workerMesh主要在以下代码中使用:


该函数是在Rebuild单个UI元素的顶点信息,红框里的FillMesh就是将更新后的顶点属性数组设置到workerMesh上,且每次调用都会先进行Clear操作。

看逻辑,这个workerMesh的内存大小应该只和单个UI元素的顶点量有关,但实际测试下来,是和当前所有激活UI元素的顶点总量相关的。

所以,Shared UI Mesh很大,表示当前所有激活UI元素的顶点总量很高。需要对部分复杂元素进行简化。

常见的复杂元素有:

  1. Tiled模式的Image:该模式下会根据UI元素的区域和纹理分辨率的大小,自动生成适当数量的四边形,一旦纹理分辨率很小,而区域很大时,就会产生大量的顶点。
  2. Outline效果的Text:Outline效果会将Text文本原来的顶点数放大为5倍。
  3. RichText,且包含了较多样式的Text:样式标签部分也会产生顶点数。

注:2和3同时使用时,样式标签部分的顶点数也会放大。

定位的方法:

  1. 初步定位:直接在SceneView下换到线框模式,肉眼找一下复杂元素;
  2. 通过Profiler的UI面板,查看各个Canvas下各个Batch产生的顶点数,并检查对应的GameObject即可。

需要注意的是,Canvas组件被禁用的情况下,Profiler里是看不到的,但其下的激活UI元素依然会影响Shared UI Mesh的大小。

该回答由UWA提供

A3:可以试试把Canvas的enable设置为false。

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


Rendering

Q1:关于阴影,GPU Skinning的Shader可以实现加上Planar Shadows的Pass吗?或是能套用Projector Render Texture吗?目前使用Unity 2018搭配GPU Skinning套用Projector投影是静态的,并不会有角色的动作;Unity 2019则是投影有动态,但显示有些错误。

图为Projector Shadow + GPU Skinning在Unity 2019安卓环境的效果。

以下是想实现的阴影方案,但不知道GPU Skinning要如何结合?请问有什么可以搭配实现阴影的插件吗?

Planar Shadows
Projector rendertexture

A1:这个问题分两个部分:

  1. 影子要跟着动作动。
  2. 影子要显示的对。

第一个部分题主已经解决了。其实原理很简单,GPU Skinning中,动画信息是先由Compute Shader或者VS的TFBO之类的东西计算好之后,传给真正绘制的VS中,通过顶点动画的方式实现动起来。

最开始没有动起来也许是因为使用的阴影Shader中,没有拿到Compute Shader或者VS的TFBO之类计算出来的动画信息,在阴影Shader的VS中进行顶点动画。

第二个问题。看上去像是典型的阴影Bias的问题(阴影中出现缝隙),题主把这个物件的阴影Normal Bias和Depth Bias都设置为0看下吧。

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

Q2:其实第一部分没有解决,用了Render Texture去投影,只是都没有处理的情况下,Unity 2019会显上上面那张图的效果,影子也会跟着动,2019以下的版本则是静态Mesh的轮廓和不会动的阴影,GPU Skinning的Shader都已经封装过,直接在Shader上加阴影的Pass是不会有任何效果的。

GPU Skinning:https://github.com/chengkehan/GPUSkinning

A1:原理就是上面那样,具体就要读代码了。据我所知Projector是用另外一个Shader绘制的,那么这个Shader中VS没做处理,肯定就不会有动画的。但是2019为什么又有了?就需要具体读代码了。

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

A2:Surface Shader:

Vertex&Fragment Shader:参考下这个https://gamedev.stackexchange.com/questions/143126/how-to-receive-shadows-on-animated-object-in-optimize-way添加一个Shadow Pass。

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

A3:根据羽飞同学的回答,做了一个对比实验,渲染的模型是Unity自带的Cylinder,在Surface Shader中加了顶点动画,效果如下图:


从上面的截图可以看到addshaow模式是可以让阴影保持正确的。上图中奇怪的部分应该是由于Camera产生的深度图(根据顶点变化后的物体生成)和Light生成的深度图(根据顶点变化前的物体生成的)对比的对象不一致导致的。

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


Script

Q:把特效直接放在Spine的节点上,在Editor里运行正常,但是在真机上特效不跟着Spine运动,可能是什么原因呢?试了一下如果是动态加载特效再挂在Spine的节点上就没问题,如果是直接保存成Prefab就不行。

A1:建议使用BoneFollower组件,让特效挂在BoneFollower组件的GameObject下。

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

A2:楼上说的对,在Spine下面创建一个GameObject,然后添加上Bone Follower Graphic组件,选择要绑定的骨骼,然后在这个GameObject下面再添加上你要播放的特效就可以了。

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


Animation

Q:我用一个原始的AnimatorController做模板文件,在编辑器里复制出来替换Clip给新的人物做动画控制器。

现在出现一个问题,用AssetDatabase.LoadAsset加载模板文件,用Instantiate复制后替换Clip后保存,发现原始的模板AnimatorController也被修改掉了。

A1:可以参考一下这个工具:AnimatorGenerator
工具介绍在此。

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

A2:建议使用AnimatorOverrideController。

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


Memory

Q:Profiler中的System.ExecutableAndDlls如何优化占用?

A1:知识的搬运工:https://answer.uwa4d.com/question/58dbbbd34e69b5ed22e68abf

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

A2:使用IL2CPP的情况下,可以搞这些事情。建议项目中期开始搞平时多测试,不建议在临近上线的时候做这方面的优化:

  • 减少C#代码,官方说1MB的C#大概会产生3MB的IL2CPP后的二进制大小。
  • Package Manager里各种用不到的Built-in Packages都去除掉。
  • 如果用的是Lua,减少不必要的Wrap代码的生成。
  • 减少link.xml里的项,preserve到类级别。
  • Managed Stripping Level使用Medium,这样未被调用的C#函数也会被删除。 (开到High可能有风险,但剔除效果明显,有时间可以尝试一下,我们一个线上项目只开到了中)。
  • 开启Strip Engine Code,尤其是安卓开启后会根据使用情况link出一个libunity.so (不开启是直接拷贝PlaybackEngines下的完整版libunity.so)。
  • iOS只保留ARM64架构。
  • 符号剔除(注意保留打包生成的symbol.zip,或者生成一个Bugly符号表,以便应对线上崩溃)。
    iOS默认会保留一部分符号,可以给XCode工程加个特殊处理。安卓对so也可以再调用一下NDK里的Strip命令。
string releaseConfig = pbxProj.BuildConfigByName(targetGuid, “Release”);
pbxProj.SetBuildPropertyForConfig(releaseConfig, “DEPLOYMENT_POSTPROCESSING”, “YES”);

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


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

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