UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - 内存
【求知探新】分享一次查找GfxDriver内存暴涨的经历
【求知探新】是UWA新推出的栏目。在大家做性能优化的过程中，常常会遇到一些未知的问题，在这里我们将分享研究这些问题的完整过程。当然需要说明的是，一个好的问题没有标准的答案，在此也欢迎大家来积极拍砖！ GFX内存为底层显卡驱动所反馈的内存分配量，主要由渲染相关的资源量所决定，它的大小也和项目的运行内存息息相关，所以我们在优化时也需要重点关注。本文，作者李星（联系邮箱：lx458004975@163.com）分享了项目研发过程中，由于GFX暴涨导致了内存崩溃的排查过程，值得参考。 一、问题描述 近期我们项目从Unity 5.5直接切换到了Unity 2017.3，颜色空间也由之前的Gamma切换到了Liner。为了测试切换大版本后，对游戏的FPS影响有多大，我们开始对一些战斗场景进行多人PVP的测试，然而经过几分钟后游戏闪退了，多次测试并且通过Logcat我们发现显存爆掉了。为了进一步的确认，我们切换到了Debug版本，通过Profiler发现GfxDriver撑的特别高，一般被爆掉的时候高达300MB以上。 二、问题分析 一般而言GfxDriver统计的内存其实就是Textures + Buffer（顶点和索引）的显存，这个在Unity 4源码中其实GfxDriver的统计也只是在提交Textures以及顶点和索引的使用调用这个统计宏，且Unity中文论坛中也有相应帖子解释http://forum.china.unity3d.com/thread-1091-1-1.html。 然而，我们观察发现Profiler统计的Textures + Meshes的内存远小于GfxDriver统计的内存，这就排除了因为资源管理不当没有及时释放资源导致的问题，因为一定时间后Textures和Meshes的内存已经相对稳定了。 三、问题排查 1、Auto Graphics API勾选的影响 之前依稀记得UWA官方群里面关于勾选Auto Graphics API后Gfxdriver暴涨的讨论，后来网络也搜索了下，找到了两个。 一个来自知乎： https://www.zhihu.com/question/60371399； 一个是UWA问答： https://answer.uwa4d.com/question/5a741b6fe3b569146eeaeb3a； 从这两个搜索到的帖子来看勾选Auto Graphics API后导致GfxDriver暴涨的可能性也还是比较大的，因此开发大神去掉了这个勾选，选择了OpenGL ES3，经历过漫长的打包等待后，再次测试验证，发现问题依然存在，并没有解决问题。 2、监控PSS，对Memory进行Detailed监控 在发现去掉勾选Auto Graphics API并不能解决问题后，又对其进行了勾选回去，同时我们对Memory进行Detailed监控，也并没有发现任何可疑的地方，因此我们再监控了下PSS，发现PSS的走势是随着GfxDriver的增长而增长。这个问题是因为显存爆掉而产生的，之前用Unity 5.5版本的时候就遇到过Android 6.0的机器会因为这个而闪退，而Android 7.0的机器却不会闪退，那么会不会是不同系统、不同手机而结果不一样呢？我们两台小米5，一台是Android 6.0，一台是Android 7.0的，测试都会闪退，用红米Note4来测试，发现居然不闪退，而且GfxDriver也挺高的。开始怀疑人生了，资源没问题，内存详情里面也看不出蛛丝马迹，关键是不同的手机居然还有不闪退的，会不会是Unity的Bug导致？ PS：这里有一点忽略了，其实在事后我们解决了问题后再回过头来看，在Detailed模式下进行Take Sample还是有一点踪迹可寻的，在Scene Memory项下可以看到Sprite的数量是飙升的，当时主要是Scene Memory的总内存数占用不大，与GfxDriver统计到的300MB多相差太远，而且我们Take Sample的次数也较少，同时在Simple面板可以看到Total Object Count的数量在涨，当时进入了误区，以为是Unity的Bug，因为Unity的坑有时候也有遇到嘛。 3、对测试场景的单个资源单个技能一一测试 在经历这么多尝试之后依然没有解决问题，同事开始了针对当前测试场景的每个特效、每个技能逐一单独进行排查。在经历了几天的排查之后告诉我找到了，是某一个游戏技能引起的，我立马打开编辑器运行到其场景，然后定位到其相应的角色及UI上，因此对其部分代码进行屏蔽，打包再次测试，终于有结果了，造成GfxDriver暴涨的就是这一段代码。 这段代码有两个影响点，一个是阴影，一个是Sprite的。因为在Memory Detailed模式下，我们并没有发现和阴影相关的问题，所以怀疑是Sprite，在粗略地浏览了下封装的Sprite的代码后，我们屏蔽了Sprite.OverrideGeometry的提交，因为这是唯一能影响显存的代码，结果事实并不能如我们所愿，因此我们改而屏蔽文字阴影，结果也是一样；后来再回到Sprite的封装上面来看，发现一个可疑之处，那就是Sprite.Create的调用，因为事前这段代码是有条件控制的，然而通过断点调试，发现每次这个UI Active后就会被调用到，那么在多人PVP的时候就会被频繁地调用，不停地去Create。最终在修改了这段逻辑控制之后，问题得到完美的解决。在开发的注释中能够发现，出现这一Bug也是为了避免Unity Sprite本身的Bug而产生的（Sprite不能Destroy掉，在多线程模式下可能会有概率在Editor、Android环境下闪退，只能等UnloadUnuse()来GC，开发传参传错了，导致每次都会创建）。当然这个问题在Unity 5.5的时候并未出现，在项目切换到Unity2017.3后才暴露出来，经过Demo测试，在高通芯片的机型上GfxDriver在几分钟内能飙升到300M+，导致闪退；而MTK芯片的机型上GfxDriver的内存则不会增长。 四、总结 问题已经解决，到了划重点的时候了，当GfxDriver内存暴涨，而Textures和Meshes的总内存又比较平稳的时候，除了可能是Auto Graphics API的问题以外，项目中是否有使用GPU Instancing呢？（这个一般比较好排除，因为当前场景有什么花啊草啊的一目了然，而且Demo验证过除非极限地去刷GPU Instancing，不然对GfxDriver的影响是非常小的），项目中是否有使用Sprite呢？而我们项目就是出在了Sprite的使用上，并且一开始通过Memory Detailed模式选项下都不能定位到问题。这里要仔细地查看每一项，而且多次对比后可能才会发现，此次就忽略了Sprite的数量，只考虑了内存大小，没有点开Scene Memory列表看，因为每次内存占用才20MB左右。 很多时候我们会遇到一些奇奇怪怪的问题，尤其是这种内存问题比较难查，可能是资源的问题，也有可能是代码的问题，还有可能是Unity本身隐藏的Bug（概率小但不排除）。个人认为排查的方法很重要（唉，技能树严重缺技能呀），再者就是需要足够的耐心和细心程度（不放过任何可疑的地方）。 文末，再次感谢李星将这篇极具参考价值的技术分享进行分享。同时，我们也欢迎大家在UWA问答社区（answer.uwa4d.com）积极提交研发过程中遇到的问题。也许随着时间的流逝，科技的进步，答案将变得廉价，但问题会变得更有价值，因为提问和研究将比回答更有力量。
本期聚集了这些话题：UGUI对于emoji表情的处理、CreatefromMemory使用策略、Resource.Load加载时的内存波动、Animator采样...... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 内存管理 Q1：我们用的是Unity 5.5.2，下图是红米2上测试的加载8个特效资源，峰值是46MB，然后就下落到22.6MB，这个内存波动是什么引起的，是因为Rendering Batches吗？ 按照题主提供的例子，UWA进行了测试，在Unity 5.5.2版本中的Android真机上确实复现出了这个问题。 加载4个粒子特效，红米2设备上，加载前内存： 加载时内存： 加载后内存，确实出现了Unity内存快速升高而又回落的“抖动”现象： 对此，我们又在Unity 5.6.2版本上进行了真机测试，同样是红米2： 加载前内存： 加载时内存： 加载后内存，虽然内存同样存在小幅抖动，但其抖动范围已经明显降低。 因此，建议研发团队尝试控制同一帧中Resources.Load的加载次数或者升级到更高Unity版本。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a40eaa2b319bedd3bec6d90 UGUI Q2：我们使用UGUI的Input Field，在手机上面如果用户输入系统自带的emoji表情，会导致一些问题，导致Input Field输入框显示异常，比如会出现一个问号的字符一直没法删除之类的，请问有什么办法可以过滤掉玩家输入的emoji表情？或者把emoji表情匹配成其他的字符？我现在是用正则来匹配emoji表情的unicode编码，但这样还是会出现覆盖不全的情况。 我们现在的处理方案，在inputfield上挂一个组件，采用类似代码来过滤表情符号，不过还没测试过能够完全符号所有表情符号，虽然不能过滤到所有的表情符号，但也不会报错。 public char ValidateInput(string text, int charIndex, char addedChar) { // Emoji表情 if (char.GetUnicodeCategory(addedChar) == UnicodeCategory.Surrogate) { return ‘\0’; } } 感谢 rubbyzhang提供了以上回答。 UWA试下来在Unity 5.5.5p2上也重现了该问题。但在Unity 5.6.2上没有这个问题。升级确实可能会带来风险，所以建议一种方法是用正则来匹配，网上一般也都用的这个方法。 第二种是建议可以试一试的，就是对比下Unity 5.5.5p2和Unity 5.6.2的UGUI的代码改动（主要是InputField的），尝试自己对照着修修看，然后自行编译UnityEngine.UI.dll。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a4448e47a38eea813706571 动画 Q3：Unity 4.x Animator 能否在编辑器下进行采样呢？比方说一个技能动作30帧，想知道每一帧下模型各个节点的坐标旋转缩放，该怎么办呢？ 1）可以在Animation窗口中直接看。 2）利用API： AnimationUtility.GetAllCurves或AnimationUtility.GetEditorCurve获取各节点的各属性AnimationCurve，然后取各AnimationCurve.keys中的keyframe的value。 之前UWA Blog里有两篇博客涉及到动画采样，GPU Skinning和动画文件降低精度，里面都有涉及采样部分的代码，建议题主可以去看看。 该问题来自UWA问答社区，感谢招文勇提供了回答，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a44ff2c997cacca2128b1e1 资源管理 Q4：不同项目的AssetBundle能够相互读取吗？有什么加密方式吗？不同的Unity版本对AssetBundle的兼容性如何？ 1）AssetBundle是可以互相读取的，只要Unity版本是对应的。 2）加密是跟一般的文件加密一样，但需要通过LoadFromMemory来进行加载，具体的方法网上有很多，建议题主可以Google一下。 3）在Unity 5.x版本中，高版本的项目是支持读取低版本的AssetBundle的，只要AssetBundle上开启TypeTree（默认开启）理论上就没问题。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a45bc64fe338d132401a799 资源管理 Q5：关于加载资源的CreatefromMemory这个API，我看到UWA不推荐使用，因为其效率很低，但是我们需要做dll的更新，我们dll是用这个加载策略的，想问下有没有什么别的方法，大家都不用这个API吗？或者有没有什么特殊情况下可以用呢？如何使得这个API的耗时降到最低？求建议，感谢！ 如果这个API仅是用来热更新代码的，那么使用它无可厚非，这个也确实是必要的，否则就是使用类似Lua的方式来进行代码热更。 UWA不推荐频繁地使用Create/LoadFromMemory这个API是指不推荐将其频繁地用在资源的加载上。如果是重要的配置文件或者dll代码，是完全可以使用这个API来进行加载的。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a40731b6f0cccd931e1f31a 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期聚集话题：Dalvik Heap 内存过高、Unity 5和Unity 2017版本下帧率降低、如何处理Animator.Initialize警告... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 内存 Q1：我们发现刚进入游戏，Dalvik Heap的内存很高，导致PSS比较高，切到后台，再切回游戏，Dalvik Heap内存减少非常多。然后我尝试使用网上说的Android调用GC的方式，System.GC，结合runFinalization。调用Runtime.getRuntime().gc()，都无法有效减少，不知道这块是否有办法有效调用一次？ 我们查到原因了，是因为我们在Android层写了一个splash，但这个splash是png的，分辨率是1920x1080，我们之前是 int splash_bg = getResources().getIdentifier(bgName, “drawable”, getPackageName()); m_BgView.setBackgroundResource(splash_bg); 这张图片在HideSplash会被处于游离状态，要等Java的GC调用后，才会回收，但实际图片按道理内存也不该涨100MB左右，我们用测试工程只有Splash和SplashVideo，发现内存并不会增长那么多，代码一模一样。后面只能解释，可能JVM后某种内存分配算法造成的，当本来比较低的情况，分配会比较少，当到达一定数量级，再分配，就会分配更大一块内存(对Android底层机制不熟) 后面我们改为先从getResources里获得BITMAP，然后给ImageView,再HideSplash时候，调用Bitmap的手动释放方法。 该问题来自UWA问答社区，感谢题主在解决后将其方法分享公开，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a2a04c27030070236a983f5 制作 Q2：我有一个MeshRenderer，它拥有两个材质，现在我想给其设置一个不同的MaterialPropertyBlocks，但据我所知，目前还没有能实现这样的办法，因为当我从Renderer中得到MaterialPropertyBlock后，我是不能指定它还能应用于某个材质了是吧？不知道大家有没有好的解决方法呢？ 是的，MaterialPropertyBlocks是以MeshRenderer为单位的，而不是以Material为单位的。只能建议题主对Mesh进行拆分，确保每个Renderer上只挂一个Material。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a263f54d99fdb2b3c628873 性能 Q3：最近项目从Unity 4 升级到Unity 5或Unity 2017时，在中低端Android机上，帧率降了10多帧，用Adreno Profiler上查了是GPU Bound。 我们游戏对帧率要求比较高， 游戏的时候必须满帧运行， 所以这个问题很明显。经过折腾，最后查出来是Unity 5 之后， 默认开启了Blit, 分辨率越高，GPU压力越大。 尤其在中低端机上，我用的是Adreno 405测试的， Unity 4能满帧， 但Unity 5或者Unity 2017最高才45左右， 简直不能忍。幸运的是，Unity 2017.2，官方终于开放了设置能禁止Blit. 但是Unity 5就没这个运气了， 根据官方的消息，他们暂时还没有计划把这个引入Unity 5.6， 具体帖子可见：https://forum.unity.com/threads/big-performance-issue-with-unity5-on-android.338847 在发现和解决问题的过程中，钱康来同学提供了不少帮助，在此感谢！开这个问题也是让大家知道下，免得像我当初摸石头过河，花太多时间折腾。 该问题来自UWA问答社区，感谢题主的无私分享，建议使用Unity 2017 或者Unity 5 版本的开发者密切注意！如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a282669a670486845f8a03d 内存 Q4：这个[Triggers RebuildInternalState]是隐藏物体就一定会触发的吗？我看Profiler里最后一列都有提示Warning，感觉挺重要的一个错误。这个要怎么去避免呢，是否会导致Animator.Initialize耗时又变得很明显(在之前有做过缓存的情况下)。 这个是含有Animation组件的GameObject被Deactive时的引擎Warning，在很多情况下确实会造成较高的CPU耗时。对此，建议题主尝试在GameObject不再需要使用时，直接将其移出屏幕外，并将其挂载的Component进行Disable，而非将其GameObject进行Deactive，这样可以RebuildInternalState的发生。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a2a62cdff95f1253a1b365e Unreal 4 渲染 Q5：你好 我看了UWA关于Unreal全局光照的那篇文章，有几点疑问想问下： 1、Unity的Lightmap烘焙时，为什么不能从Normal map获取Normal信息呢？我看Unreal的Lightmass也是烘焙出两张图，一张方向一张颜色。它的颜色可以受NormalMap的影响吗？ 2、Unreal的一个场景多张Lightmap，例如白天到晚上，渐变是怎么融合的呢？ 1、Lightmap中的Directional信息是指烘焙光照的方向信息。在Lightmap中一张是记录光照的Intensity，一张是记录Direcitonal，这个Directional是用来参与Shading中方向相关计算的，例如：高光计算、与normal计算等。如果是纯Dffuse材质也不用Normalmap，这个Directional信息可以去掉，减少存储和计算量。通常在材质中看到的Normalmap指的是Mesh的Normal与Lightmap中记录的Directional并不是同一个值。 2、Unreal中的Precomputed Lighting Scenarios是保存了多套Lightmap以及光照设置，只能做到配合光照进行Lightmap切换，融合现在貌似还做不到。 Q5：烘焙的时候光照的Intensity考虑Normal就类似beast那样，Lightmass烘焙的时候可以提供Normalmap吗？ 我是这样理解的：Unity烘焙的时候用了辐射度，也就是先把模型分成块，然后计算快与块之间的反射，不会使用Normalmap。Normalmap提供的是细节的信息，全局光照中间接光的计算结果相对比较低频，比较平滑，加入高频的信息不一定会有好的效果。Unreal 4的lightmass可以有一个选项设置Static类型的光源在烘焙的时候使用normal map，其设在project settings->engine rendering->lighting中。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a28b0592de8d7470d08f62e 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期聚集话题：Unity资源卸载API使用技巧、Reserved Total Unity内存的变化问题、MangedHeap.UseSize的数值一直在变化... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 内存 Q1：我写了一个用例加载AssetBundle，并将多个特效Prefab实例化到场景中。连续运行了多次用例并把添加的特效对象都删除，而且切换了场景，我看到Profiler中的内存变化如下图所示： 我想咨询下： 1. Profiler里的Reserverd Unity内存比Used Unity内存高出很多是正常的吗？ 2. 如果正常的话，有办法可以回收Reserverd Unity内存吗？ 3. Reserverd Unity内存在运行完多次上述的用例后稳定在400MB，再运行一次用例可以上涨到450MB，虽然后面会回落到400MB。这样的表现也是正常的吗？ 题主这个数据是在Editor中做测试的结果吗？Reserverd比Used高出这么多确实不太合理；但如果是Editor中，那么Unity其实会做很多辅助操作，这些也确实是会占用内存的。所以，建议在真机中测试看看，看看这个差距是否会下来。但如果是在真机中，那么这个差距确实过高了，不太合理。 Reserverd Unity的内存是引擎自身管理的，一般会在后续不使用时自己降下来。 这种升高和回落是正常的，但至于是否应该这么高，请见1中的回答。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a1fde25bd7d86f726903207 内存 Q2：我想咨询下，Resources.UnloadUnusedAssets() 在卸载旧场景后加载新场景前调用好，还是在加载新场景后调用比较好呢？如果考虑内存峰值的话，我觉得是前者好，但是在UWA上看到有些文章说是加载场景后调用，所以想深入学习下。 如果题主是通过LoadLevel(Async)类似的方式来加载场景的话，那么Unity自身会在底层执行一次类似Resources.UnloadUnusedAssets的操作。所以，这时如果手动调用Resources.UnloadUnusedAssets操作，时间间隔很短，其实这个是有些重复的。因此，我们才建议在新场景加载后再调用一次。 但如果题主使用LoadLevelAdditive或其他类似的API来切换场景的话，那么Unity是不会调用Resources.UnloadUnusedAssets的，这时你再旧场景卸载后调用，其实也是很不错的选择。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a1fc7dbbd7d86f726903206 渲染 Q3：是否可以认为Shader里 Blend Off和Blend One Zero是完全等价的？我在Unity的Standard Shader里看到它的混合是使用形如Blend [_SrcBlend] [_DstBlend]来动态控制，并且注意到其在StandardShaderGUI.cs里设置Opaque时就是设置的 Blend One Zero，那么是否可以认为在Shader里写Blend One Zero的话，和Blend Off是等价的？Unity会自动改变blendstate从而避免从destbuffer读取数据？ 我们在Unity 2017.1上测试了一下，发现实际上在Android平台的GLES调用中，Unity的Standard Shader的Opaque模式是在disable blend的状态下渲染的，实验如下： 设备：红米2。渲染场景是两个Standard Shader Opaque模式物体（Sphere和Cube），中间有一个Unlit Transparent的Quad： 通过Android工具查看GLES API调用发现，每一帧渲染Cube和Sphere的时候Blend都是关闭状态（上一帧结束时关掉），然后在渲染Unlit Transparent的Quad时打开： 其中，36个顶点的DC是渲染Cube，2304个顶点的DC是渲染Sphere，6个顶点的 DC是渲染quad。所以看起来Standard Shader的Opaque模式应该是glDisable(GL_BLEND)的状态下渲染的。 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a1a8e710aef30913881b489 内存 Q4：在游戏每次打完副本回到主界面后，内存数据总是不太一致，其中通过Unity Profiler我观察到ManagedHeap.ReservedUnuseSize和ManagedHeap.UseSize的数值一直在变化，请问这个变化是否是合理的？ ReservedUnuseSize和ManagedHeap.UseSize一直在变化是正常的，它们都属于Mono内存，前者是当前Mono内存中没有使用的，后者是正在使用的。一般游戏中，Mono堆内存是会经常由代码来进行分配的，所以这两个值一直在变化，也是很正常的情况。 这里建议题主密切关注以下两点： （1）Mono的总堆内存是否一直在升高 下图是UWA性能测评报告中的Mono堆内存走势图，其中的紫色线条即为项目运行时的ManagedHeap.UseSize，而黄色线条为ReservedUnuseSize，这两者都是在变化的，但最需要关心的是蓝色线条Reserved Mono，这条线条如果持续往上走，那么就说明项目中是很可能出现了内存泄露问题，需要研发团队彻查，建议通过Mono详细堆内存分析来进行修复。 （2）具体的堆内存分配是否合理 ManagedHeap.UseSize或者Mono总内存的上升都是由于代码的堆内存产生的，所以查看代码堆内存分配是否合理，避免不必要的堆内存分配是非常重要的，类似于下图。 建议题主参考以下两篇文章： 用正确的方式，三天搞定Mono堆内存泄漏！ Unity游戏的代码堆内存优化 该问题来自UWA问答社区，如您对该问题仍有疑问，可以转至社区进行进一步交流。 https://answer.uwa4d.com/question/5a24efc0355737361cc410c9 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
今天我们为大家带来由上海非钰数码科技的FPS手游《战地先锋》的 UWA测评报告分析。该游戏在各种档次的移动终端设备上，无论是画面表现力，还是性能开销都非常优异。在此，我们将对该款游戏的性能数据进行深度剖析，希望通过这篇文章可以让大家对移动游戏各个模块的运行效率有更为深刻的认知，并对大家的项目研发有所帮助。 一、CPU性能 该游戏在CPU占用方面的性能非常不错，下图为该游戏在红米Note2 设备上按照剧情进行游戏时的性能数据。可以看出，在红米Note2 上运行的24979帧中，超过33ms的帧数占比为4.3%，超过50ms的帧数占比为1.2%。考虑到切换场景时资源加载的开销，一款游戏如果超过33ms的帧数占比低于10%，则说明该游戏在绝大多数时刻的运行中都是非常流畅的。 通过进一步统计，该游戏的CPU性能超过了84%的红米Note2设备上的测试游戏，其能耗更是低于91%的同设备测试游戏。 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。下面，我们就详细讲解一下其CPU性能方面的亮点之处。 1、渲染模块 通过UWA性能测评报告，我们可以看到该游戏详尽的渲染模块性能开销。该游戏在红米Note2设备上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为1.5 ms，主要集中在 0.7~2.7ms 范围内（5%~95%）。不透明物体渲染的CPU消耗均值为1.8 ms，主要集中在 0.2~4.6ms范围内（5%~95%）。 Draw Call峰值为340，虽然峰值较高，但仅在场景切换处出现，这是因为项目在动态加载后通过代码调用StaticBatching的方式来合并Draw Call，所以可以看到Draw Call数量在进入场景后迅速回落。同时，Draw Call数量主要集中在 48~179 范围内（5%~95%），属于合理范围之内。 下图为该游戏在红米Note2上的具体CPU性能堆栈。可以看到，该游戏在红米Note2上无论是不透明开销还是半透明开销均处于较低水平，这得益于研发团队对于场景模型、蒙皮网格和UI的控制十分得当。 美中不足的是Shader.SetPass稍高，这主要是渲染模块中RenderState的切换较为频繁所致，对此，建议大家对场景中的Material数量进行控制，具体可以参考：《使用MaterialPropertyBlock来替换Material属性操作》 2、UI模块 该游戏在红米Note2设备上运行时的UI模块CPU开销如下图所示。该游戏使用UGUI作为UI界面的解决方案。经过统计，UI模块总体的CPU占用均值为1.9ms，主要集中在0.1~3.6ms范围内（5%~95%），属于合理范围之内。 其均值高于70%的行业数据，这是因为该项目使用的是Unity 4.7版本进行开发，该Unity版本中，UGUI并没有像Unity 5.3版本以后将部分拼合操作放到子线程中进行。在这一点上，Unity 4.x的UGUI性能较之5.3+版本确实要多一些性能上的开销。堆内存平均每帧分配为5.5B，仅高于5%的行业项目，这说明该游戏UI界面的制作及UI重建的影响范围非常合理。目前，UWA推荐UGUI模块中，平均每帧堆内存分配尽可能控制在2KB以下。 从下图中可以看出，Canvas.SendWillRenderCanvases在不同的运行时刻均出现CPU高值，但通过运行截图可以看到，其共同特点是CPU耗时高值均发生在画面底层的UI选人界面出现时。因此，该UI界面的出现或相关操作极有可能是引发Canvas.SendWillRenderCanvases CPU过高的原因，建议研发团队对该界面进行进一步检测。 3、动画模块 在UWA测评报告中，该游戏运行时的动画模块CPU开销如下图所示。 可以看出，除进入场景时出现CPU高值外，其在战斗副本中的CPU开销均控制在较低水平。Animator.Update的CPU均值为1.8ms，主要集中在0.1~3.4ms区间内，其性能较为优秀，高于28%的行业项目。同时，MeshSkinning.Update的CPU均值为1.8ms，主要集中在0.1~3.4ms区间内，高于21%的行业数据。 同时，经过进一步检测发现，其进入副本时的CPU高值均为lhAnimatorEvent.OnEventCallback回调函数所致，具体的CPU耗时堆栈如下图所示。通过此堆栈可知，其耗时主要为UI界面的加载耗时，且进一步通过资源管理信息可知其主要开销为luaUI_PK(Clone)的Active操作和luaUI_Hall(Clone)的Deactive操作所致。因此，建议研发团队可进一步检测该UI的制作是否合理，并对其进行完善。 4、GC调用 该研发团队对于GC调用频率控制得非常出众，游戏在运行过程中，GC调用频率为1921帧/次，优于目前95%的行业内游戏。 一般来说，如果一款项目的GC调用频率可以控制在1000帧/次以上，就已经相当出众了。该游戏的GC调用频率如此优秀，主要得益于研发团队对于项目代码堆内存的控制。下图为游戏运行25000帧的代码堆内存具体分配情况。对于使用UGUI的游戏来说，我们建议游戏运行每1万帧中，Top10函数的堆内存分配总和小于30MB，而该游戏运行25000帧，其Top10函数的堆内存分配总和才26.91MB，足见该团队对于堆内存分配的理解非常深刻。 二、内存模块 《战地先锋》在内存上的表现如下图所示。总内存峰值达到249MB，Mono堆内存峰值为32.5MB。243MB的总内存分配相对来说略高，研发团队可尝试在低端机器上对资源进行进一步控制，从而降低低端机器上的内存占用。 1、Mono堆内存 从上图可知，该游戏的总体Mono堆内存控制得很好，在25000帧中，Mono的堆内存峰值仅为 32.5MB。该值属于合理范围之内（<40MB）。 但是，从走势上来看，其堆内存的占用在游戏运行过程中持续处于上升趋势，对此，建议研发团队对缓存池进行进一步检测，排查项目是否存在堆内存泄露的隐患。 2、资源内存 经过统计，该游戏的纹理资源数量峰值为618个，内存占用峰值119.5MB。纹理内存占用较高，目前高于82%的行业项目。经过统计，在内存占用峰值处，ETC1格式纹理占有221个，Alpha8格式纹理占有5个，RGBA32和ARGB32格式纹理共占有120个，RGB24格式纹理占有87个，其余为RGBA16格式纹理。 对于RGBA32、ARGB32的纹理，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理（Android平台）进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。而对于无法进行硬件压缩的纹理，可以通过Dither方法尝试将其转换成RGBA16格式的纹理，具体做法可以参考此篇文章。 其他资源的内存占用情况如下： Mesh资源： 内存峰值高于41%的项目 AnimationClip资源： 内存峰值高于40%的项目 AudoClip资源： 内存峰值高于73%的项目 AudioClip的内存占用较高，高于73%的行业项目。对此，研发团队可尝试将内存占用较高的音频资源通过Stream的方式来进行加载，该方式可极大降低AudioClip资源的内存占用。 以上则为《战地先锋》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、非常少的堆内存分配以及引擎模块间的合理使用，足以看出该研发团队非常深厚的技术功底和对于引擎相当优秀的把控能力。 三、性能优化、进无止境 该游戏在Shader加载和GameObject Active/Deactive方面仍有一定的提升空间。在此，我们对其进行罗列，希望同样可以帮助到大家的研发项目。 1、Shader加载 目前，游戏副本切换时存在较高的Shader解析（Shader.Parse)开销，如下图所示。通过具体资源信息中的Shader资源分析，可以定位是如下几个Shader的加载耗时，对此，建议研发团队尝试对频繁使用的Shader进行预加载并常驻内存，从而减少不必要的Shader重复加载耗时。 2、GameObject Active/Deactive调用次数过高 该游戏在运行过程中，GameObject Active/Deactive的调用次数过高，在游戏运行的25000帧中，Active调用268952次，Deactive调用393490次。其调用的具体次数如下图所示（下图为游戏运行每10帧进行一次Sample，而每个Sample的数值为前10帧中Active/Deactive调用次数的总和。 其中，GameObject的Active/Deactive Top10资源信息具体如下所示，因此，研发团队可通过下表直接对频繁进行Active的GameObject进行完善。Deactive的完善亦然。 频繁的Active/Deactive操作不仅会造成CPU的浪费，同时，它还很可能间接造成更大的CPU耗时，比如Animator.Initialize耗时。该游戏的Animator.Initialize调用较为频繁，且耗时较高，如下图所示，而这就是频繁的Active/Deactive操作所造成的结果。因此，对于GameObject不必要的Active和Deactive操作进行控制，是非常有必要的。 最后，非常感谢《战地先锋》研发团队对 UWA 的认可和支持。感谢他们乐于将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的3D移动游戏在各个模块上可以做到怎样的程度。同时，也欢迎更多的开发团队可以与我们一起来分享你们的性能数据，让更多的游戏开发者受益！ PS：安利这款FPS手游，在TapTap上已经获得了8.6的高分，并将于9月7日在14个安卓渠道同时开启付费删档测试，欢迎大家来预约！ 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 2）资源检测与分析 3）UWA GOT 三大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。
过去的一年，MOBA手游市场容量变得空前庞大，成了众多CP和发行追捧的对象，同时，其重社交、重玩法、重美术效果的高要求使得该品类游戏也面临着前所未有的性能挑战，那么当下市场上的MOBA手游性能呈什么样的状态呢？我们能从这一年的性能数据中找到什么规律呢？今天，我们将为大家分享MOBA手游性能的深度剖析。 今天分享的这份蓝皮书，收集了提交到www.uwa4d.com上的所有MOBA项目，我们从总体性能数据、引擎各模块开销、内存占用等方面进行了汇总分析，呈现Unity手游行业现状。 这是侑虎科技第291篇原创文章，欢迎转发分享，未经官方授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。（QQ群：793972859） 报告目录： 一、MOBA手游总体性能开销分析 二、MOBA手游CPU模块性能开销分析 三、MOBA手游内存模块性能开销分析 四、MOBA手游资源管理分析 五、UWA对于MOBA手游研发团队的建议 说明：我们选择了测评次数最多的四款机型来进行统计，这四款机型分别是红米2、红米Note2、华为6Plus和三星S6。同时，由于中低端设备性能是研发团队更为关注的部分。因此，本报告中的性能趋势分析以MOBA项目在中低端设备的性能数据为主。 一、MOBA手游总体性能开销分析 Android设备的CPU均值主体范围为16~61.2 ms，且主要集中在17~50ms范围之内。 无论是高、中、低端的Android设备，渲染、UI、加载/代码都是需要研发团队重点关注的，它们的消耗总和占了总开销的80%。 下面我们就来具体分析这些主流模块的开销情况。 二、MOBA手游CPU模块性能开销分析 1、渲染模块 严重程度：地狱 为了能够更好地反映出各个性能参数的整体使用情况，我们统计了每种性能参数的主体使用范围，其范围区间是[5%~95%]，以下数据中P5代表5%，P95代表95%。 在Draw Call使用上，MOBA手游的使用程度大幅低于MMORPG和ARPG手游，且对Draw Call的控制同样较好，UWA建议Draw Call占用的P95 < 200，86%的项目可以将其控制在这个范围内。 MOBA手游的场景渲染三角形面片数量普遍较高。且设备性能越高，数量峰值越高。经过统计，在中低端设备中，46.6%的项目能将渲染三角形面片数控制在100K以下。 2、UI模块 严重程度：地狱 使用NGUI作为UI解决方案的项目占据了相当高的比例，NGUI目前仍然是MOBA研发团队对于UI系统使用的主要解决方案。MOBA是目前手游中工程技术难度最为复杂的游戏品类之一，对于UI模块的选择，大多数团队仍然倾向于从稳定性和把控性两方面出发，这也是NGUI占比持续较高的主要原因。 下面我们将分别说明NGUI和UGUI的CPU耗时和堆内存占用情况。 UI模块的性能开销依然很高，也是我们统计中的重要性能杀手。在中低端设备上，超过80%的研发项目在UI端都面临较为严重的性能问题，主要体现在以下几个方面： （1）同一时刻存在大量需要更新的Panel，比如，攻击时刻的血条、不断移动的伤害数字等HUD。这些在“人堆”中范围攻击时或者进攻高地时是很容易大面积出现的； （2）不断滑动的摇杆和点击的技能icon，这些是MOBA战斗场景中使用最为频繁的UI元素，研发团队需要时刻注意这些icon的变动是否会带来较大范围内的重建。 以上情况都是MOBA项目研发团队每天面对的主要UI问题，可能一个Widget的使用疏忽，就能让研发团队的UI模块性能开销飙升一个量级。 注意：从重要函数上来看，UGUI的CPU占用大幅低于NGUI。需要说明的是，Unity 5.2版本之后已经开始将UI的部分计算操作移到子线程中进行，而主线程中的表现则为WaitingForJob、PutGeometryJobFence等，在本次报告中，我们并没有将这两项开销统计在内。 经统计，NGUI中堆内存每10000帧分配的主体范围为 5.4~53.2 MB，UGUI中堆内存每10000帧分配的主体范围在5.2 MB以内。从堆内存分配来看，UGUI远低于NGUI。 3、逻辑代码 严重程度：噩梦 1）GC触发频率很高，是造成卡顿的主要原因之一，目前只有48.7%的项目可以将GC的触发频率控制在1000帧/次以上。 2）在2016年GC平均耗时下降趋势明显，但在2017Q2出现大幅上升趋势，对此，建议研发团队在后续研发过程中对GC操作和耗时进行密切关注。 Shader.Parse 操作是比较突出的性能杀手，目前平均每次调用的CPU耗时主要分布在 6.4~171.3ms。但随着越来越多团队了解该项的耗时特性后，该项的CPU耗时呈现出较为明显的下降趋势。 4、动画模块 严重程度：噩梦 Animator.Update/Animation.Update的开销在中低端设备上的耗时呈现逐步升高趋势，对此，建议研发团队重点查看本篇文章的最后一节，我们提供了进一步完善和优化动画模块性能的相关方法。 5、粒子模块 严重程度：普通 1）粒子系统的CPU开销普遍很低，且近一年来下降趋势较为明显。 2）粒子系统的数量使用仍然较大，这会造成较高的内存占用，虽然2016 Q4和2017 Q1已经大幅下降，但2017 Q2随着新项目的增加，粒子系统的使用数量又开始大幅增加。MOBA项目中存在粒子系统数量较大的原因，主要是特效和技能的缓存所致。为了保证战斗时（特别是团队时）技能释放的流畅性，研发团队会选择在场景加载时即缓存英雄的所有技能，因此，MOBA游戏在战斗副本中会出现较大量的粒子系统缓存现象，特别需要研发团队关注。 三、MOBA手游内存模块开销分析 1、总体内存 严重程度：地狱 可以看到，MOBA游戏总体内存在2016年上升趋势明显，而在2017年内存占用则较为稳定。为了兼容市面上的中低端机，Unity引擎的实际内存占用需要尽可能被控制在300MB以下，这点是各大MOBA研发团队今年优化阶段的重中之重。 2、总体堆内存 严重程度：地狱 堆内存使用在2016年大幅下降，但今年随着新项目的涌入，其上升趋势明显，建议研发团队重点关注。对此，UWA建议重点关注以下几点： 1）严格关注配置文件的使用，避免一次性加载过大的配置文件而撑大堆内存； 2）不少项目的堆内存增大是由于热更新所致。因此，对于过大的数据Data的使用，建议通过分帧进行，并及时进行GC回收； 3）避免不必要的代码堆内存分配，虽然是老生常谈，但从趋势上可以看出，大多数研发团队仍需加强重视。 项目的内存占用很大一部分来自于资源的使用，下面我们将对项目中主流资源的使用情况进行分析。 3、纹理资源内存 严重程度：地狱 1）纹理内存峰值主要分布为 40~147.3 MB。 2）从走势中可以看到，随着MOBA项目的精品化趋势，其纹理内存占用也大幅提升，虽然2017Q2稍有下降，但依然拥有较高的内存占用。 4、网格资源内存 严重程度：噩梦 网格资源内存峰值主要分布为 14.1~ 65.9 MB，且上升趋势明显。对于场景、角色的网格资源控制，是研发团队在后续研发团队中需要关注的重点。 5、动画资源内存 严重程度：普通 动画资源内存峰值主要分布在9.2~38.5 MB以内，从走势中可以看出，2017Q1的内存占用达到47.1MB，而2017Q2的内存占用迅速回落到18.4MB。经过进一步分析，其主要原因如下： 1）2017Q1大量新游戏的涌入直接提升了该阶段的内存占用； 2）2017Q2动画资源新优化方式的推广，大量研发团队从中受益，从而内存占用大幅回落。关于动画资源的优化建议，建议研发团队查看UWA之前推送的技术文章《Unity动画文件优化探究》。 6、Shader资源内存 严重程度：噩梦 Shader资源内存峰值占用主要集中在0.1~7.9 MB区间之内。需要提醒的是，研发团队需要密切关注Standard Shader的使用情况，因为该类Shader在解析时不仅会造成较高的CPU开销，同时会造成较大量的内存占用。 7、RenderTexture资源内存 严重程度：普通 与MMORPG和ARPG手游不同，RenderTexture在MOBA游戏中的内存占用保持在较低的水平，在2016Q3出现41.2MB的高值后，迅速回落，并稳定在25MB左右的内存占用。 8、粒子系统资源内存 严重程度：噩梦 与粒子系统的开销一致，其内存占用也在2017年呈现持续大幅上升趋势。粒子系统的内存占用主要与其内存中缓存的数量相关，对此，建议研发团队在后续研发中对粒子系统的使用进行密切关注和严格控制。 四、MOBA手游资源管理分析 在资源加载方面，AssetBundle.Load是项目中的主要加载方式，且主要集中在场景切换处。就目前的MOBA游戏而言，绝大多数项目使用的加载方式仍然是同步加载。 1）New WWW是MOBA项目中AssetBundle的主要加载方式。 2）LoadFromFile(Async)的使用在2017 Q2上大幅增加，但整体仍然较少，仅占10.5%。这主要是因为市面上仍有不少MOBA项目使用的是Unity 4.x版本所致。但如果您的项目目前是使用Unity 5.x版本开发，建议尝试升级到Unity 5.3版本以后，并通过LoadFromFile(Async)的方式进行加载。 Instantiate/Destroy和Active/Deactive调用次数较高，需要研发团队根据自身项目情况时刻注意： 1）由于Active/Deactive每次调用的CPU开销不大，且不会造成崩溃、闪退等问题，所以研发团队极易忽视这两项操作所带来的性能问题，因而出现了游戏运行1万帧Active/Deactive上万次调用的情况。因此，此处存在着很大的性能浪费； 2）Instantiate/Destroy的调用次数同样较高，但与MMORPG和ARPG游戏不同的是，Instantiate调用主要发生在场景切换处，大量GameObject在Instantiate实例化后被缓存使用，而为了保证战斗时的足够流畅，战斗过程中研发团队大多通过Active/Deactive操作来代替Instantiate/Destroy操作； 3）Destroy操作大幅高于Instantiate操作。经过进一步分析，这主要是由于当前MOBA项目中NGUI使用占比较高所致。在对NGUI制作的UI界面（比如血条等HUD）进行Deactive操作是MOBA战斗过程中较为频繁的操作，而此Deactive操作会引发UI底层Destory相关的Material操作。所以会出现Destory次数次数大幅高于Instantiate次数的情况。 五、UWA 对于MOBA手游研发团队的建议 MOBA是移动游戏研发难度较高的品类，其对于性能的严苛要求可谓达到了“寸土寸金”的地步。目前国内仍然在开发MOBA类移动游戏的，也都是技术实力与情怀兼备的团队。正因如此，MOBA游戏在很多模块中的性能表现已经较为优秀。对此，我们对于MOBA项目研发团队的优化建议如下： 1、渲染方面，Draw Call的控制技术已被MOBA研发团队所熟练掌握。随着玩家的设备质量提升，建议研发团队考虑GPU Instancing技术，该功能已经在Unity 5.5版本以后被支持，由于MOBA项目的特殊性，研发团队可以考虑将其应用在场景中的草、树木等大量重复物体重，从而进一步降低渲染模块在CPU端的开销。但是，需要注意的是，GPU Instancing的技术虽然可以降低Draw Call，但仍需要节制使用，因为其在移动设备上的GPU和能耗方面的压力可能会让你大吃一惊。 2、UI方面，与其他游戏类型一样，UI网格重建开销在未来相当长的一段时间内仍然是研发团队头痛的问题，UI优化的原则非常简单：动静分离，但真实操作起来则是非常困难。90%项目中的UI性能问题是由于动静元素没有分离导致，但没有任何两个项目的具体原因是一致的。这是UI性能优化方面非常困难的主要原因。 3、逻辑代码方面在上述报告中并没有特别谈及，这主要因为MOBA类型的项目，其在战斗时的逻辑代码开销主要为自身开销，即项目自身的AI、同步等操作，其主要包括小兵和怪物的攻击搜索、寻路操作、位置和状态的持续更新等等。对此，建议研发团队关注其AI操作的调用频率和单位开销是否合理。 4、动画模块方面，随着MOBA游戏中怪物、小兵和英雄的角色复杂程度越来越高。建议研发团队考虑通过GPU Skinning + GPU Instancing的方式缓解大量蒙皮网格在动画模块和渲染模块中的性能开销，具体做法可参见《GPU Skinning加速骨骼动画》。 5、在内存优化方面，Mono、网格和粒子系统内存占用在2017年的上升趋势非常明显，对此，建议研发团队在接下来的项目研发中密切关注这两项的内存使用。 6、资源加载方面，New WWW仍然是MOBA研发团队的主流AssetBundle加载方式，但我们建议正在使用Unity 5.x的研发团队，使用LoadFromFile(Async)的方式来对AssetBundle进行加载。对于仍然没有使用该方式的研发团队，建议查看UWA博客上的相关文档（blog.uwa4d.com），并找到对应的性能比较和分析。 7、 以上数据是我们对于MOBA手游性能数据的整体研究和趋势分析，旨在从宏观上为大家展现项目中普遍存在的性能瓶颈和研发团队容易忽视的潜在性能问题。但同样需要说明的是，优化是一个“抽丝剥茧”的过程，需要研发团队花费大量的时间和耐心去完成。UWA建议：多做测试，以数据说话，空杯心态，将经验归零。 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 2）资源检测与分析 3）UWA GOT 三大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。
Hello, 各位Unity开发者，无论您是正用着UWA的工具、还是阅读着UWA的相关技术文章亦或是在UWA博客中寻找一个问题的解答，我们都倍感荣幸能和你在此相遇。本篇可以说是UWA产品服务的向导，认真读完它，您会了解UWA究竟是做什么的，并且如何利用UWA提供的资源和工具。在与UWA的日益接触中，您会发现它不仅能为你们项目的性能保驾护航，还能少走很多弯路，缩短优化的时间。 Part 1. 优化工具 Q：UWA提供哪些可以快速提升性能的工具？ 这个要从UWA的定义说起，UWA由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）线上性能测评 2）UWA GOT 3）UWA GOT Online 三大工具。下面我们将分别介绍。 一、线上性能测评 1、性能检测与优化 通过真人真机对项目测试，提供针对性的性能报告和优化方案，既能从宏观上分析项目运行时的整体趋势，包括总体CPU性能、GC调用频率和引擎各模块性能等，也能从微观上深入剖析内存管理、资源使用以及逻辑代码在运行时的效率瓶颈。研发团队通过对报告提供的方案进行针对性的优化，能在短期内提升项目的运行效率。 入手方法：该服务主要通过在UWA官网上提交项目的测试包（apk、ipa等，无需工程源码）来完成。由UWA工作人员测试分析后，会提供针对该项目的性能报告和分析建议，可以在此参考报告demo。 该工具分为免费版和收费版，免费版一个月可以使用一次。强烈推荐大家来试试免费版哦！ 2、资源检测与分析 反馈资源的打包情况，包括具体包含的资源情况、详细的依赖关系和资源的冗余程度等。用户通过优化报告指出的冗余问题来实现减小包体、减小内存并提升加载速度的目的。 入手指南：用户在UWA官网上传AssetBundle包（无需游戏包），一旦上传，UWA将自动开启检测并返回结果，一般时长在30分钟以内（视AB包体量而定），可以在此参考报告demo。 该工具永久免费使用，无使用次数限制。 二、本地性能测试工具：UWA GOT UWA GOT 全称 Game Optimization Toolkit，是由侑虎科技研发的本地性能测评工具。它既能方便研发团队在本地直接进行真机测试，也支持在Unity Editor中搭建本地服务器来接收和分析性能数据。整个测试过程中，研发团队能自定义测试时间和流程，几分钟后即可查看性能数据，同时还提供深度的数据分析，如脚本中的主要函数耗时、堆内存的具体分配堆栈等高级分析功能，从此为大家的项目性能又增添一份安全堡垒！ 具体功能说明：戳此传送门 入手指南：戳此传送门 价格：RMB399，包括维护和更新 三、UWA GOT Online UWA GOT Online是基于其本地测评模式上的线上同步功能，研发团队可以将本地测评的数据快速同步到UWA官网，生成在线测评报告。除了“本地化”和“快”这两大天然优势，我们目前提供了四大性能检测模式：总体性能检测、Mono堆内存分析、运行时资源检测和Lua性能分析来满足大家的优化需求。 具体功能说明：戳此传送门 入手指南：戳此传送门 Part 2. 干货大全 一、引擎把握篇 性能卡顿、内存泄露、资源冗余...这些开发中遇到的疑难杂症大部分都能在这里找到解决方法，它们无不通过大量的项目深度优化和周而反复的测试验证。如果你想避开一些不必要的坑，请务必啃下这些硬货！ 1.1 Unity性能优化进无止境——CPU篇 从渲染、UI、加载等几个重要维度分析了目前大部分项目中存在的CPU性能问题和解决方案 1.2 Unity性能优化进无止境之内存篇（基础篇） 谈优化必谈内存，该文深入浅出地分析了Unity项目的内存占用 1.3 Unity性能优化进无止境之内存篇（进阶篇） 内存泄露、Mono无效堆内存、资源冗余...你关注的内存问题都在这里！ 1.4 AssetBundle打包机制详解（5.x） （4.x 版本的API接口有所差别，请看这里） 1.5 AssetBundle内存管理机制 AssetBundle真是个绝妙的设计，但是想说爱你不容易！ 1.6 Profiler中常见的高CPU耗时函数 1.7 代码热更新（dll反射） 亘古不变的话题了 1.8 加载模块详解（纹理篇） 加载龟速？是时候来点加速度了！ 1.9 加载模块详解（网格篇） 1.10 加载模块详解（Shader篇） 1.11 加载模块详解（动画资源） 二、提升：工欲善其事，必先利其器 在这里不仅有效果拔群、性能出众的插件帮助大家省心省力，也有卧虎藏龙的民间高手抛钻引玉给大家分享自己的优化技巧。 1、UI相关 2.1.1 UGUI 降低填充率技巧两则 2.1.2 如何优化UGUI的ScrollRect 2.1.3 UGUI表情系统解决方案 2.1.4 UGUI 文本多语言方案 2、制作相关 2.2.1 毛发及眼球的渲染技术 2.2.2 游戏中的角色渲染技术之皮肤篇 2.2.3 卡通渲染及其相关技术总结 2.2.4 Unity移动端动态阴影总结 2.2.5 合并Shader系列 | 如何合并渲染状态 2.2.6 如何打造高逼格耀斑效果 2.2.7 Unity线性空间下移动设备上烘焙变暗问题处理 2.2.8 Unity 5烘培场景带来的“爱”与“愁” 2.2.9 GPU Skinning 加速骨骼动画 2.2.10 如何精简Unity中使用的字体文件 2.2.11 使用MaterialPropertyBlock来替换Material属性操作 2.2.12 Unity图片优化神器 - Dither算法进阶方案 2.2.13 布料系统原理浅析和在Unity手游中的应用 2.2.14 聊聊Unity里的嵌套Prefab 2.2.15 如何实现更真实的软阴影效果 2.2.16 开启HDR时，半透明渲染画面异常的解决方案 2.2.17 使用Fast Shadow Receiver优化渲染效率 2.2.18 Unity+ iPhone X适配方案 2.2.19 Unity手游开发札记——使用Shader进行UGUI的优化 2.2.20 iOS下拆分Unity图集的透明通道（不用TP） 2.2.21 Journey中的沙丘渲染及其Shader实现 2.2.22 扩展Unity模型编辑器 2.2.23 如何在Unity中实现Stochastic Screen Space Reflection效果 2.2.24 高效的iPhone X适配技术方案（UGUI和NGUI） 2.2.25 如何大幅优化NGUI的堆内存分配 2.2.26 如何在Unity中实现Stochastic Screen Space Reflection效果 2.2.27 基于Unity引擎的Bent Normal实现 2.2.28 Unity移动平台下的烘焙使用及优化 2.2.29 基于2D SDF的体积字实现 2.2.30 Unity如何实现投影阴影效果 2.2.31 Unity引擎后处理性能优化方案解析 2.2.32 利用多进程并行化加速Unity资源构建 2.2.33 Unity引擎iOS增量编译方法解析 3、插件&工具相关 2.3.1 插件 | 那些你不得不用的好插件！——工具篇 2.3.2 插件 | 你的项目和大作只差一个插件的距离！——美术效果篇 2.3.3 插件 | 好插件让你事半功倍！——资源篇 2.3.4 技巧 | Unity中Avatar换装实现 2.3.5 插件 | Unity一键图集生成工具，附源码 (基于NGUI和TexturePacker) 2.3.6 插件 | Unity游戏界面解决方案: PSD For UGUI 2.3.7 插件 | ShaderForge插件分享 2.3.8 技巧 | ScreenSpaceShadowMask Blur推荐 2.3.9 插件 | USequencer系列 |初识 2.3.10 插件 | USequencer 准确显示瞬时事件和持续事件 2.3.11 插件 | USequencer 缤纷事件、事件间吸附 2.3.12 屏幕特效插件分析 | FxPro & Beautify 2.3.13 屏幕后处理特效性能分析—运动模糊 2.3.14 Unity插件开发基础—浅谈序列化系统 2.3.15 如何高效定位Unity安卓开发中的闪退问题 2.3.16 ACT技能编辑器的制作经验分享 4、内存相关 2.4.1 Lua性能优化—Lua内存优化 2.4.2 用好Lua+Unity，让性能飞起来——Lua与C#交互篇 2.4.3 用好Lua+Unity，让性能飞起来—LuaJIT性能坑详解 2.4.4 Unity项目常见Lua解决方案性能比较 2.4.5 Lua配置表存储优化方案 2.4.6 Unity匿名函数的堆内存优化 2.4.7 给调皮的AssetBundle加上面向对象式加载调试管理 2.4.8 Unity 5.x AssetBundle零冗余解决方案 2.4.9 AssetBundle进阶内存优化（Unity 4.x） 2.4.10 巧用UWA资源检测，轻松剔除冗余资源！ 2.4.11 听说你的项目中仅这些资源就卡成了翔？看看他们怎么做！ 2.4.12 Lua的CPU开销性能优化 2.4.13 我所理解的委托和匿名函数 5、研发实录 2.5.1 我们用50次游戏性能的深度优化，总结出了五条“毒鸡汤” 2.5.2 Unity手游开发札记—大世界动态加载实战 2.5.3 Unity手游iOS内存分析和测试 2.5.4 Unity 协程运行时的监控和优化 2.5.5 Unity 游戏的String interning优化 2.5.6 Unity动画文件优化探究 2.5.7 动画重定向技术分析及其在Unity中的应用 2.5.8 VR交互动画短片《拾梦老人》的开发经历 2.5.9 独立游戏《Abi》场景耗时分析 2.5.10 Optimize GameObject选项对骨骼Transform的影响 2.5.11 《为谁而炼金》UI界面加载性能分析 2.5.12 Unity中ShaderLab内存优化 2.5.13 使用UWA GOT优化Unity性能和内存 2.5.14 客户端配置文件优化策略 2.5.15 Unity中字体名对依赖关系的影响 2.5.16 《小米超神》技术总监王啸予：重度MOBA的优化之路 2.5.17 基于团队的持续优化之道 2.5.18 《Exploring in UE4》多线程机制详解 6、行业参考 2.6.1 UWA发布 | 2017 Unity手游体检蓝皮书 — ARPG篇 2.6.2 UWA发布 | 2017 Unity手游体检蓝皮书 — MMORPG篇 2.6.3 UWA发布 | 2017 Unity手游体检蓝皮书 — MOBA篇 2.6.4 Unity版本使用情况统计报告 7、案例精讲 2.7.1 UWA助力独立游戏开发！《江湖X：汉家江湖》性能诊断精讲！ 2.7.2 一次MMO手游的性能诊断全纪录 2.7.3 RPG |《星辰奇缘》测评精讲 2.7.4 ARPG|《王者之剑2》性能数据精讲 2.7.5 RPG |《仙剑奇侠传3D回合》性能精讲 2.7.6 ACT |《艾尔战记》性能精讲 2.7.7 MMO |《六龙争霸》测评精讲 2.7.8 FPS |《全民枪战》测评精讲 2.7.10 FPS手游《战地先锋》性能案例精讲 2.7.11 MOBA手游《小米超神》案例精讲 2.7.12 UWA官方Demo新增《小米超神》，全面揭秘重度手游的性能表现！ 8、学术论文 2.8.1 基于功耗预算的实时绘制 2.8.2 微表面模型－PBR渲染管线的材质 2.8.3 基于物理的渲染—更精确的微表面分布函数GGX 2.8.4 基于物理的渲染—基于球面调和基的实时全局光照明 2.8.5 基于物理的渲染—基于Haar小波基的实时全局光照明 2.8.6 基于物理的渲染－用真实的环境光照亮物体 2.8.7 基于物理的渲染—HDR Tone Mapping 2.8.8 CG中的深度学习 |Siggraph 2017 相关论文总结 Part 3. UWA 问答社区 所有的已知，在未知面前不过是冰山一角。遇到问题怎么办，投石问路！正所谓不学不问，不问不知。一个高质量的提问是解决问题的一半。如果你真心想解决某个问题，不妨和大家一起来讨论下这些话题吧。 3.1 资源放到resource下面有什么优势和劣势 3.2 如何降低动画文件的浮点数精度 3.3 AssetBundle 粒度规划 3.4 数据模板表打包以及加载方式怎么做可以兼顾加载速度和热更新表结构 3.5 资源引用最后导致应用包体大小的疑惑 3.6 AssetBundle未加载完使用错误 3.7 项目初期如何确定美术规范 ... UWA问答社区地址：answer.uwa4d.com 关于我们的官方QQ群（465082844） 如果你也想做出高颜值的代码，如果你也期待能让项目走向性能巅峰，如果你本人也乐于分享从善如流，欢迎加入UWA群；与其闭门造车不如群策群力；比起形而上学，我们更乐于解决实际问题。 Part 4. UWA 自学素材 UWA不仅举办了多次技术优化日，也积极活跃在网络。我们尽己所能，将技术的触角传递到每个角落。以下就是我们留下的足迹： 4.1 8.10 直播回顾 | 一个小时内，我们用UWA GOT解决了这些问题... 4.2 UWA 六月直播季 | 6.29 Unity UI模块中的优化案例精讲 4.3 UWA 六月直播季 | 6.22 Unity中动画系统性能优化方案回顾 4.4 UWA 六月直播季 | 6.15 Unity引擎渲染效率全解析 4.5 UWA 六月直播季 | 6.8 移动游戏加载性能和内存管理全解析 4.6 5.4 UWA直播回顾：Unity游戏的代码堆内存优化 4.7 NGUI性能优化技巧（上） 4.8 NGUI性能优化技巧（下） 4.9 UGUI美术制作——如何实现次时代美术效果 4.10 UGUI性能优化技巧 4.11 请让我用一小时，将你的项目性能提升一个高度！ 4.12 UWA优化日厦门站回顾 | 资深TA教你如何将艺术概念转化为渲染代码 4.13 不喧哗，自有声—记UWA优化日深圳站（附完整技术PPT） 4.14 记一次冷雨寒风日的UWA优化日（内附技术PPT） 4.15 You should be here ！| 附UWA优化日技术PPT Part 5. 虚幻引擎学习之路 我们会将UWA内部学习过的Unreal相关技术文档进行总结和整理，并陆续发布，计划发布两大系列文章，第一个系列是功能篇，主要讲述我们学习过程中所了解到的Unreal引擎功能特色；第二个系列是性能篇，重点分析Unreal引擎在多个平台（特别是移动平台）上的性能效率。 5.1 虚幻引擎学习之路：渲染模块之光照系统 5.2 虚幻引擎学习之路：渲染模块之材质系统 5.3 虚幻引擎学习之路：相机图像后处理 5.4 虚幻引擎学习之路：渲染模块之全局光照明 5.5 虚幻引擎学习之路：动画模块之基础篇 5.6 虚幻引擎学习之路：动画模块进阶篇之动画融合 5.7 虚幻引擎学习之路：动画模块进阶篇（二） 5.8 虚幻引擎学习之路：粒子系统篇（一） 5.9 虚幻引擎学习之路：粒子系统篇（二） 5.10 虚幻引擎学习之路：新粒子系统Niagara 5.11 虚幻引擎学习之路：基于Unreal引擎的大地形加载研究 与其他世面文章不同的是，我们会在讲解中揉入和Unity引擎相似功能的对照说明，以方便大家更快地对其进行理解和掌握。这里，需要郑重说明的是，我们之所以这么做并不是为了比较Unreal引擎和Unity引擎谁更强大，二者都是当今世界上伟大的引擎。我们这么做是因为发现这可以极大地提高对于Unreal引擎的学习效率。 到这里便是UWA迄今为止所有在Blog以及微信上推送的技术博文汇总，我们将其梳理，是为了让一些经典好文能够重现，让知识能常流通，同时也是为了方便大家日后查找。本篇文章作为UWA Blog里的目录将随时更新，建议大家Mark起来，有空没空随手刷上个两篇，结合自身的研发项目多做测试加深理解，UWA相信一定事半功倍。 最后也要感谢所有向UWA供稿的开发者，感谢你们将这么棒的想法分享出来，从而帮助到更多的研发团队。当然如果你也有好的想法或者研发路上的心得体验，也可以分享给我们哦（support@uwa4d.com），知识的百科全书需要你我共筑。
接上期UWA 发布的2017 Unity手游体检蓝皮书MMORPG篇，本期我们将深度剖析ARPG的游戏性能发展情况。此份蓝皮书收集了提交到www.uwa4d.com上的所有项目，我们从总体性能数据、引擎各模块开销、内存占用等方面进行了汇总分析，呈现Unity手游行业现状。 这是侑虎科技第275篇原创文章，欢迎转发分享，未经官方授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。（QQ群：793972859） 报告目录： 一、ARPG手游总体性能开销分析 二、ARPG手游CPU模块性能开销分析 三、ARPG手游内存模块性能开销分析 四、ARPG手游资源管理分析 五、UWA对于ARPG手游研发团队的建议 一、ARPG手游总体性能开销分析 iOS设备的CPU性能普遍高于Android设备，Android设备的CPU均值主体范围为12.4~66.2 ms，iOS设备的CPU均值主体范围为7.0~57.5 ms。 我们选择了测评次数最多的四款机型来进行统计，这四款机型分别是红米2、红米Note2、华为6Plus和三星S6。 1）大部分ARPG手游在中低端设备的性能开销较高，在Android设备上，CPU耗时集中在17~50ms区间，而在iOS设备上，CPU耗时集中在33ms以内。 2）相较2016年同期，2017 Q2 ARPG手游在低端设备上的CPU开销均值增长5.8 ms。 无论是高、中、低端的Android设备，渲染、UI、加载/代码都是需要研发团队重点关注的，它们的消耗总和占了总开销的80%。 下面我们就来具体分析这些主流模块的开销情况。 二、ARPG手游CPU模块性能开销分析 1、渲染模块 严重程度：地狱 为了能够更好地反映出各个性能参数的整体使用情况，我们统计了每种性能参数的主体使用范围，其范围区间是[5%~95%]，以下数据中P5代表5%，P95代表95%。 在Draw Call使用上，ARPG手游的使用程度略低于MMORPG手游，且对Draw Call的控制同样较高，UWA建议Draw Call占用的P95 < 200，76.3%的项目可以将其控制在这个范围内。 1）ARPG手游的场景渲染三角形面片数量普遍较高。且设备性能越高，数量峰值越高。经过统计，在中低端设备中，46.5%的项目能将渲染三角形面片数控制在100K以下。 2）ARPG游戏的场景复杂程度明显低于MMORPG游戏，渲染面片峰值要比MMORPG手游平均低50K。同时，虽然2016 Q4和2017 Q1渲染面片数量大幅上升，但2017 Q2开始回落趋势较为明显。 Graphics.Bilt操作平均每次调用的CPU耗时主要分布在: 0.1~8.5ms。该项CPU开销在低端设备上的上升趋势较为明显，但在2017 Q1大幅下降。这主要是因为，在2017 Q1后，ARPG项目普遍开启了多线程渲染功能。 2、UI模块 严重程度：地狱 使用NGUI作为UI解决方案的项目占据了较高的比例，但从趋势上来看，UGUI从2016 Q3开始，增速非常明显。通过进一步分析，我们发现近大半年来的新ARPG手游中，使用UGUI的项目显著增加，从而大幅提升了UGUI在ARPG项目中的使用占比。 下面我们将分别说明NGUI和UGUI的CPU耗时和堆内存占用情况。 UI模块的性能开销依然很高，也是我们统计中的第二大性能杀手。在中低端设备上，超过90%的研发项目在UI端都面临较为严重的性能问题，主要体现方面与MMORPG游戏类似，功能界面复杂、同一时刻需要更新的Panel多等。但ARPG的平均耗时要略低于MMORPG，这是因为ARPG主要仍以推图形式为主，其在战斗副本中的玩家是预先固定的，大量玩家同屏打怪的情况很少出现。 经统计，NGUI中堆内存每10000帧分配的主体范围为 6.0~81.7 MB，UGUI中堆内存每10000帧分配的主体范围在12.3 MB以内。从堆内存分配来看，UGUI远低于NGUI。 3、逻辑代码 严重程度：噩梦 1）GC触发频率很高，是造成卡顿的主要原因之一，目前只有12.5%的项目可以将GC的触发频率控制在1000帧/次以上。 2）在2017年GC平均耗时趋势虽有所上升，但相比于2016年已经大幅降低。 1）Instantiate实例化操作平均每次调用的CPU耗时主要分布在: 1.2~43.5 ms，且主要集中在10ms以内。 2）Instantiate实例化耗时在2017 Q2之后大幅下降，这说明越来越多的研发团队开始重视项目运行时的资源管理。 Shader.Parse 操作是比较突出的性能杀手，目前平均每次调用的CPU耗时主要分布在 4.4~145.2ms。但随着越来越多团队了解该项的耗时特性后，该项的CPU耗时呈现出较为明显的下降趋势。 4、动画模块 严重程度：噩梦 1）Animator.Update/Animation.Update的开销在中低端设备上的耗时普遍较高，但整体耗时在2017年上半年有明显的下降趋势。 2）ARPG游戏的MeshSkinning.Update的耗时明显高于MMORPG游戏。这主要体现在角色模型的面片数和骨骼数方面，ARPG更加偏向于动作表现力上。 5、粒子模块 严重程度：普通 1）粒子系统的CPU开销普遍较低，且近一年来下降趋势较为明显。 2）粒子系统的数量使用仍然较大，这样会造成较高的内存占用。UWA建议将粒子系统的使用数量峰值控制在400以下，目前仅21.8%的项目达到。 6、物理模块 严重程度：普通 物理模块的性能普遍较好，但呈现出较为明显的上升趋势，因此在中低端机上依然需要研发团队关注。 三、ARPG手游内存模块开销分析 内存泄露是研发过程中经常面临的严峻问题，依然有37%的项目存在不同程度的内存泄露。我们可以看到从2016 Q2开始，内存泄露占比大幅下降，但随着项目新功能的开发以及新项目的涌入，其占比又开始大幅攀升回来。虽然整体趋势有所下降，但内存泄露问题的有效防范和解决，依然任重道远。 1、总体内存 严重程度：地狱 1）总体内存峰值主要分布在95.6~573.9 MB区间，且均值在300MB以上。 2）与MMORPG游戏相比，ARPG内存占用的上线起伏更加明显。经过进一步分析，我们发现，2016 Q4的内存占用在大多数老项目中的主要资源（纹理、网格和动画片段等）都得到了较大的内存优化；但随着2017 Q1新项目不断涌入，内存占用又大幅回升；而2017 Q2内存的下降则是因为AssetBundle内存的大幅下降，大多数研发团队开始通过LoadFromFile来加载LZ4格式的AssetBundle，从而让内存又迅速回落。 2、总体堆内存 严重程度：地狱 1）总体堆内存峰值主要分布为 9.7~109.6 MB，仅37.7%的项目可以把总体堆内存峰值控制在40MB以内。 2）堆内存使用上升趋势明显，建议研发团队重点关注。对此，UWA建议重点关注以下几点： 严格关注配置文件的使用，避免一次性加载过大的配置文件而撑大堆内存； 不少项目的堆内存增大是由于热更新所致。因此，对于过大的数据Data的使用，建议通过分帧进行，并及时进行GC回收； 避免不必要的代码堆内存分配，虽然是老生常谈，但从趋势上可以看出，大多数研发团队仍需加强重视。 项目的内存占用很大一部分来自于资源的使用，下面我们将对项目中主流资源的使用情况进行分析。 3、纹理资源内存 严重程度：地狱 1）纹理内存峰值主要分布为 22.4~198.8 MB，且主要分布在50~100MB区间。 2）内存峰值占用在2016 Q4大幅下降，但在今年后又开始逐步上升，建议研发团队密切关注自身项目的纹理资源使用情况。 4、网格资源内存 严重程度：噩梦 1）网格资源内存峰值主要分布为 1.0~ 47.5 MB，且主要集中在40MB以内。 2）ARPG游戏的场景较之MMORPG游戏普遍较小，场景相对轻量和简单，因此，其网格资源量明显低于MMORPG游戏。 5、动画资源内存 严重程度：噩梦 动画资源内存峰值主要分布在38.7 MB以内，且主要集中在15MB以内。 6、Shader资源内存 严重程度：噩梦 1）Shader资源内存峰值主要分布在6.1 MB之内，且主要集中在1MB之内。 2）从内存趋势上来看，近一年来内存占用下降较为明显。 7、RenderTexture资源内存 严重程度：地狱 1）RenderTexture资源内存峰值主要控制在67.7 MB以内，且在各个区间都较为平均。 2）内存使用上升趋势明显，建议研发团队对其在自身项目中的使用情况特别关注！ 8、粒子系统资源内存 严重程度：噩梦 1）粒子系统资源内存峰值主要分布在 33.7 MB以内，且主要集中在20MB以内。 2）粒子系统的内存占用一直较为平稳，虽然在2011年Q1期间高端机上的内存占用较高，但在2017年Q2则大幅回落到之前水平。 3）目前，粒子系统的内存占用仍然较为“虚高”，即游戏运行期间Active数量远小于内存中的总数量，在大部分项目中，Active的粒子系统数量占比不到10%，即粒子系统的内存占用峰值应该在5MB左右。 四、ARPG手游资源管理分析 1）在资源加载方面，AssetBundle.Load和Resources.Load是项目中的主要加载方式。 2）通过调用趋势可以看出，研发团队对于Resources.Load的使用仍然有明显的增长趋势。对此，UWA强烈建议研发团队尽可能使用AssetBundle作为游戏资源的主要加载方式。 1）LoadFromFile(Async)是ARPG项目中AssetBundle的主要加载方式。 2）LoadFromFile(Async)的使用在2017 Q2上大幅增长了46%，这是在UWA DAY 2017上我们非常建议的AssetBundle加载方式(Unity 5.3版本后)，研发团队可以通过UWA Blog(blog.uwa4d.com)的相关文章查看具体的性能对比。 Instantiate/Destroy和Active/Deactive调用次数较高，需要研发团队根据自身项目情况时刻注意： 1）由于Active/Deactive每次调用的CPU开销不大，且不会造成崩溃、闪退等问题，所以研发团队极易忽视这两项操作所带来的性能问题，因而出现了游戏运行1万帧Active/Deactive上万次调用的情况。因此，此处存在着很大的性能浪费； 2）Instantiate/Destroy的调用次数同样较高，虽然不如Active/Deactive频繁，但每3帧调用1次Instantiate的频率依然不容忽视，建议研发团队坚持加强项目的资源管理，避免不必要的频繁Instantiate/Destroy操作发生。 五、UWA 对于ARPG手游研发团队的建议 一、警惕渲染模块和UI模块这两大性能杀手！随着精品化ARPG项目的日益增多，在日后很长一段时间内，这两项依然将是研发团队在性能优化方面的重中之重！ 渲染方面，Draw Call的控制技术已被越来越多的团队所熟练掌握，并且随着设备的发展，Draw Call的影响将越来越小，反观渲染Triangle数量将逐步成为渲染模块的新的性能瓶颈，越来越大的渲染Triangle量会给GPU、耗电和发热方面带来巨大的压力； UI方面，UI网格重建开销在未来相当长的一段时间内仍然是研发团队头痛的问题，UI优化的原则非常简单：动静分离，但真实操作起来则是非常困难。90%项目中的UI性能问题是由于动静元素没有分离导致，但没有任何两个项目的具体原因是一致的。这是UI性能优化方面非常困难的主要原因。 二、逻辑代码方面，Instantiate实例化开销虽然在2017 Q2呈现较为明显的下降趋势，但仍需要研发团队持续对资源管理进行监控。同时，GC开销的上升趋势明显，需要研发团队加强对Mono堆内存的优化意识； 三、在内存优化方面，与MMORPG游戏类似，Mono和RenderTexture内存占用在2017年的上升趋势非常明显，对此，建议研发团队在接下来的项目研发中密切关注这两项的内存使用； 四、在动画模块方面，ARPG游戏的CPU耗时明显高于MMORPG游戏。对此，我们的建议如下： 尝试动画片段的精度缩减技术，该技术在UWA Blog和UWA问答上（answer.uwa4d.com）都有详细的讲解和代码分享； 由于ARPG游戏对于动作表现力的要求很高，因此，相比于Humanoid模式，Generic模式更加适合于ARPG项目，它可以让你的动画表现与3DMax、Maya等制作表现更加一致； 随着ARPG中怪物角色的数量持续增加，GPU Instancing技术会受到更多游戏团队的青睐，具体做法可参加UWA Blog相关文章。但同样需要注意的是，研发团队需要控制同屏的渲染面片数。 五、资源加载方面，Resources.Load依然是比较主流的资源加载方式。但UWA建议尽可能尝试通过AssetBundle.Load来加载相关资源。在2017 Q2以后，LoadFromFile(Async)已经成为ARPG研发团队的主流AssetBundle加载方式，对于仍然没有使用该方式的研发团队，建议查看UWA的相关直播信息，并找到对应的性能比较和分析； 六、以上数据是我们对于ARPG手游性能数据的整体研究和趋势分析，旨在从宏观上为大家展现项目中普遍存在的性能瓶颈和研发团队容易忽视的潜在性能问题。但同样需要说明的是，优化是一个“抽丝剥茧”的过程，需要研发团队花费大量的时间和耐心去完成。UWA建议：多做测试，以数据说话，空杯心态，将经验归零。 以上就是UWA发布的2016-2017年ARPG手游性能测评汇总和分析。此次，我们从性能参数上增加了资源加载、资源卸载等数据扩充了报告的完整性，在测评参数上加入了机型、历史数据等方便研发团队能及时进行横向和纵向的比较。我们深信数据是会说话的，总有规律值得我们追溯求实、鉴往知来。同时我们也会不断细化评析的标准、划分，以使得这些数据更有代表性和说服力。 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 2）资源检测与分析 3）UWA GOT 三大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。
正值UWA成立两周年之际，借着China Joy蓄势待发之势，UWA发布2016-2017年Unity手游性能测评数据分析蓝皮书，希望能为游戏行业的从业人员提供详实的信息和针对性的建议。 此份蓝皮书收集了提交到www.uwa4d.com上的所有项目，我们从总体性能数据、引擎各模块开销、内存占用等方面进行了汇总分析，这呈现Unity手游行业现状。 这是侑虎科技第269篇原创文章，欢迎转发分享，未经官方授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。（QQ群：793972859） 报告目录： 一、MMORPG手游总体性能开销分析 二、MMORPG手游CPU模块性能开销分析 三、MMORPG手游内存模块性能开销分析 四、MMORPG手游资源管理分析 五、UWA对于MMORPG手游研发团队的建议 一、MMORPG手游总体性能开销分析 iOS设备的CPU性能普遍高于Android设备，Android设备的CPU均值主体范围为14.4~73.6 ms，iOS设备的CPU均值主体范围为9.2~43.5 ms。在Android设备上，CPU耗时集中在17~50ms区间，而在iOS设备上，CPU耗时集中在33ms以内。 我们选择了测评次数最多的四款机型来进行统计，这四款机型分别是红米2、红米Note2、华为6Plus和三星S6。 1）大部分MMORPG手游在中低端设备的性能开销较高，大于33ms的耗时占比范围在60%~70%。 2）精品化过程中的MMORPG手游在低端移动设备上的CPU开销明显增大。相较2016年同期，2017 Q2 MMORPG手游的CPU开销均值增长超过50%。 无论是高、中、低端的Android设备，渲染、UI、加载/代码都是需要研发团队重点关注的，它们的消耗总和占了总开销的80%。 下面我们就来具体分析这些主流模块的开销情况。 二、MMORPG手游CPU模块性能开销分析 1、渲染模块 严重程度：地狱 为了能够更好地反映出各个性能参数的整体使用情况，我们统计了每种性能参数的主体使用范围，其范围区间是[5%~95%]，以下数据中P5代表5%，P95代表95%。 MMORPG手游的Draw Call数量普遍较高，且设备性能越好，数量峰值越高。这主要有以下几方面原因： 1）研发团队普遍开始针对不同机型来制定自适应的渲染LOD策略，主要包括模型LOD和Shader LOD等。 2）除LOD外，研发团队同样会对一些渲染效果进行有针对性的设置，最常见的是阴影的处理，高端机上开启实时阴影，而低端机上则通过较为简单的阴影面片或Projector来处理。另外，水体模拟也越来越多地在项目中被使用，高端设备上开启水面反射效果，也会增加一定量的Draw Call。 但就目前数据表明，研发团队已经开始有意地对Draw Call进行控制，UWA建议Draw Call占用的P95 < 200，72.3%的项目可以将其控制在这个范围内。 1）MMORPG手游的场景渲染三角形面片数量普遍较高。且设备性能越高，数量峰值越高。经过统计，在中低端设备中，40.4%的项目能将渲染三角形面片数控制在100K以下。 2）场景复杂程度明显增加，虽然2017 Q2数量有所回落，但相较于去年同期，仍然增幅33%。同时，较高的渲染面片数量也大幅增加了中低端设备的GPU渲染压力和耗能压力。 Graphics.Bilt操作平均每次调用的CPU耗时主要分布在: 0.1~5.1ms。与Instantiate开销类似，该项CPU开销在低端设备上的上升趋势较为明显，但在2017 Q2大幅下降。这主要是因为，在2017 Q1后，MMORPG项目普遍开启了多线程渲染功能。 2、UI模块 严重程度：地狱 使用NGUI作为UI解决方案的项目占据了相当高的比例，NGUI目前仍然是MMORPG研发团队对于UI系统使用的主要解决方案。MMORPG是目前手游中工程技术难度最为复杂的游戏品类之一，对于UI模块的选择，大多数团队仍然倾向于从稳定性和把控性两方面出发，这也是NGUI占比持续较高的主要原因。 下面我们将分别说明NGUI和UGUI的CPU耗时和堆内存占用情况。 UI模块的性能开销依然很高，也是我们统计中的第二大性能杀手。在中低端设备上，超过90%的研发项目在UI端都面临较为严重的性能问题，主要体现在以下几个方面： （1）MMORPG游戏的界面复杂，功能多（技能、背包、角色、任务、商城等），数量大（血条、名称、飘字等HUD）。 （2）同一时刻存在大量需要更新的Panel，比如，移动中血条等HUD、NPC不断更新的提示icon、面板中（任务、首充等）的提醒动画、聊天框和弹幕中随机出现的滚动文字等。 以上情况都是MMORPG项目研发团队每天面对的主要UI问题，可能一个Widget的使用疏忽，就能让研发团队的UI模块性能开销飙升一个量级。 注意：从重要函数上来看，UGUI的CPU占用大幅低于NGUI。需要说明的是，Unity 5.2版本之后已经开始将UI的部分计算操作移到子线程中进行，而主线程中的表现则为WaitingForJob、PutGeometryJobFence等，在本次报告中，我们并没有将这两项开销统计在内。 经统计，NGUI中堆内存每10000帧分配的主体范围为 6.1~103.3 MB，UGUI中堆内存每10000帧分配的主体范围在10.9 MB以内。从堆内存分配来看，UGUI远低于NGUI。 3、逻辑代码 严重程度：噩梦 1）GC触发频率很高，是造成卡顿的主要原因之一，目前只有10%的项目可以将GC的触发频率控制在1000帧/次以上。 2）随着MMORPG游戏越来越重度化，GC平均耗时在逐步上升。GC耗时会逐渐成为游戏运行时的主流性能杀手，需要研发团队时刻注意！ 1）Instantiate实例化操作平均每次调用的CPU耗时主要分布在: 1.4~33.1 ms，且主要集中在10ms以内。 2）Instantiate实例化耗时在2017 Q2之前一直处于上升趋势，但在2017 Q2中大幅下降，这说明越来越多的研发团队开始重视项目运行时的资源管理。 Shader.Parse 操作是比较突出的性能杀手，目前平均每次调用的CPU耗时主要分布在 5.8~134.4ms。但随着越来越多团队了解该项的耗时特性后，该项的CPU耗时呈现出较为明显的下降趋势。 4、动画模块 严重程度：噩梦 1）Animator.Update/Animation.Update的开销在中低端设备上的耗时普遍较高，但整体耗时在2017年上半年明显降低。 2）MeshSkinning.Update的耗时普遍较低。 5、粒子模块 严重程度：普通 1）粒子系统的CPU开销普遍较低，且近一年来下降趋势较为明显。 2）粒子系统的数量使用仍然较大，这样会造成较高的内存占用。UWA建议将粒子系统的使用数量峰值控制在400以下，目前仅24.8%的项目达到。 6、物理模块 严重程度：普通 物理模块的性能普遍较好，但呈现出较为明显的上升趋势，因此在中低端机上依然需要研发团队关注。 三、MMORPG手游内存模块开销分析 内存泄露是研发过程中经常面临的严峻问题，依然有将近半数的项目存在不同程度的内存泄露。但我们可以看到，内存泄露的比例正在逐步降低，相较于去年同期，2017 Q2的内存泄露占比已经下降了6%。 总体内存 严重程度：地狱 1）总体内存峰值主要分布在146.8~576.9 MB区间，且均值在350MB以上； 2）随着MMORPG游戏的精品化趋势，其内存占用也逐步增加，虽然2016 Q4稍有回落，但整体内存的上升趋势较为明显。 总体堆内存 严重程度：地狱 1）总体堆内存峰值主要分布为 18.3~117.2 MB，仅34.2%的项目可以把总体堆内存峰值控制在40MB以内； 2）堆内存使用上升趋势明显，建议研发团队重点关注。对此，UWA建议重点关注以下几点： 严格关注配置文件的使用，避免一次性加载过大的配置文件而撑大堆内存； 不少项目的堆内存增大是由于热更新所致。因此，对于过大的数据Data的使用，建议通过分帧进行，并及时进行GC回收； 避免不必要的代码堆内存分配，虽然是老生常谈，但从趋势上可以看出，大多数研发团队仍需加强重视。 项目的内存占用很大一部分来自于资源的使用，下面我们将对项目中主流资源的使用情况进行分析。 1、纹理资源内存 严重程度：地狱 1）纹理内存峰值主要分布为 27.8~174.6 MB，且主要分布在50~100MB区间； 2）内存峰值占用在2016 Q4大幅下降，但在今年后又开始逐步上升，建议研发团队密切关注自身项目的纹理资源使用情况。 2、网格资源内存 严重程度：噩梦 1）网格资源内存峰值主要分布为 8.5~ 70.4 MB，且主要集中在40MB以内； 2）MMORPG游戏的场景普遍较大、角色普遍较多，因此，其网格资源量明显高于其他类型游戏。但从使用趋势上来看，其最近一年的使用趋势较为平稳，均值均在30MB上下浮动。 3、动画资源内存 严重程度：噩梦 1）动画资源内存峰值主要分布在: 3.5~ 58 MB，且主要集中在15MB以内。 2）内存使用趋势较为平稳，平均峰值内存长期控制在20~25MB区间之内。 4、Shader资源内存 严重程度：噩梦 1）Shader资源内存峰值主要分布为 0.1~ 5.6 MB，且主要集中在1MB之内。 2）从内存趋势上来看，2016年内存占用下降较为明显，2017年略有上升。 5、RenderTexture资源内存 严重程度：地狱 1）RenderTexture资源内存峰值主要分布为 0.1~ 100.9 MB，且在各个区间都较为平均； 2）内存使用上升趋势明显，建议研发团队对其在自身项目中的使用情况特别关注！ 6、粒子系统资源内存 严重程度：噩梦 1）粒子系统资源内存峰值主要分布为 1.3~ 34.8 MB，且主要集中在20MB以内； 2）粒子系统的内存占用在2016年Q3期间较高，而后在2016年Q4大幅下降，但仍然还有较大的下降空间。目前，粒子系统的内存占用较为“虚高”，即游戏运行期间Active数量远小于内存中的总数量，在大部分项目中，Active的粒子系统数量占比不到10%，即粒子系统的内存占用峰值应该在5MB左右。 四、MMORPG手游资源管理分析 1）在资源加载方面，AssetBundle.Load和Resource.Load是项目中的主要加载方式； 2）通过调用趋势可以看出，研发团队对于Resources.Load的使用仍然有增加的趋势。对此，UWA强烈建议研发团队尽可能使用AssetBundle作为游戏资源的主要加载方式。 1）LoadFromFile和New WWW是项目中AssetBundle的主要加载方式； 2）LoadFromFile的使用在2017 Q2上升了6%，这是在UWA DAY 2017上我们非常建议的AssetBundle加载方式（Unity 5.3版本后），研发团队可以通过UWA Blog的相关文章查看具体的性能对比。 Instantiate/Destory和Active/Deactive调用次数较高，需要研发团队根据自身项目情况时刻注意： 1）由于Active/Deactive每次调用的CPU开销不大，且不会造成崩溃、闪退等问题，所以研发团队极易忽视这两项操作所带来的性能问题，因而出现了游戏运行1万帧Active/Deactive上万次调用的情况。因此，此处存在着很大的性能浪费； 2）Instantiate/Destory的调用次数同样较高，虽然不如Active/Deactive频繁，但每5帧调用1次Instantiate的频率依然不容忽视，建议研发团队坚持加强项目的资源管理，避免不必要的频繁Instantiate/Destory操作发生。 五、UWA 对于MMORPG手游研发团队的建议 一、警惕渲染模块和UI模块这两大性能杀手！随着精品化MMORPG项目的日益增多，这两项在接下来很长一段时间内依然是研发团队在性能优化时的重中之重！ 渲染方面，Draw Call的优化技巧已被越来越多的团队所熟练掌握，并且随着设备的发展，Draw Call的影响将越来越小，反观渲染Triangle数量将逐步成为渲染模块新的性能瓶颈，越来越大的渲染Triangle量会给GPU、耗电和发热等带来巨大的压力； UI方面，UI网格重建开销在未来相当长的一段时间内仍然是研发团队头痛的问题，目前手游MMORPG仍然处于“端游手游化”的转变初期阶段，大多数研发团队考虑更多的仍是功能上的迁移和与移动端的结合，在UI技术上的沉淀较为薄弱。 二、 逻辑代码方面，Instantiate实例化开销虽然在2017 Q2呈现较为明显的下降趋势，但仍需要研发团队持续对资源管理进行监控。同时，GC开销上升趋势明显，需要研发团队加强对Mono堆内存的优化意识； 三、内存泄露占比持续下降，但内存占用持续升高。虽然移动设备的内存量逐年增大，但对于希望覆盖面广阔的游戏团队来说，内存的控制仍然刻不容缓； 四、在内存优化方面，大部分研发团队都将精力放在纹理、网格和动画片段等主要资源上，但通过上述分析发现，Mono堆内存和RenderTexture内存占用在2017年的上升趋势非常明显，对此，建议研发团队在接下来的研发中密切关注这两项的内存使用； 五、动画资源和粒子系统的内存优化空间依然很大。对于前者，建议研发团队关注以下技术： 动画片段的精度缩减技术，该技术在UWA Blog和UWA问答上都有详细的讲解和代码分享； 关注Retargeting技术，该技术可以大幅降低多角色的动画片段内存占用，预测随着MMORPG项目的进一步重度化，该技术会得到越来越多团队的青睐。 对于后者，则建议研发团队关注粒子系统的资源配表，结合UWA线上性能报告，对不常使用的Particle System进行合理规划。 六、资源加载方面，New WWW、Resources.Load依然是研发团队非常常用的资源加载方式。但UWA建议尽可能尝试通过LoadFromFile(Async)和AssetBundle.Load来加载相关资源，从而获得更好的性能。研发团队可在UWA Day 2017的相关Blog中找到对应的性能比较和分析； 七、以上数据是我们对于MMORPG手游性能数据的整体研究和趋势分析，旨在从宏观上为大家展现项目中普遍存在的性能瓶颈和研发团队容易忽视的潜在性能问题。但同样需要说明的是，优化是一个“抽丝剥茧”的过程，需要研发团队花费大量的时间和耐心去完成。UWA建议：多做测试，以数据说话，空杯心态，将经验归零。 以上就是UWA发布的2016-2017年MMORPG手游性能测评汇总和分析。此次，我们从性能参数上增加了资源加载、资源卸载等数据扩充了报告的完整性，在测评参数上加入了机型、历史数据等方便研发团队能及时进行横向和纵向的比较。我们深信数据是会说话的，总有规律值得我们追溯求实、鉴往知来。同时我们也会不断细化评析的标准、划分，以使得这些数据更有代表性和说服力。 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 2）资源检测与分析 3）UWA GOT 三大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。
本期我们聚集了这些话题：Physics性能开销、iOS设备上的ZFighting、AssetBundle资源冗余、UI性能优化... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间20分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 物理模块 Q1：在游戏里没有使用物理（Physics)相关功能时，怎么把物理相关的性能消耗降到最低？ 我们游戏里完全没用到物理相关的功能，只是因为需要做点击碰撞检测，所以GameObject上需要加上BoxCollider组件，但是Profile时会时不时看到Physics.Processing的消耗有点高，也不算非常高，但是理论上如果完全没用物理相关功能的话，总感觉这部分消耗是可以完全干掉的，对于Profiler中Physics模块中给的几个统计不太清楚是怎么计算的，目前使用的Unity版本是5.3.6f1版本。 就我们目前的分析来看，在Unity5.4版本之前，物理模块是会每帧都运行的。而在Unity5.4版本之后，如果没有使用任何物理相关的功能时（Rigidbody、CharacterController、Rogdoll、Cloth模拟等等），物理模块会被关闭。所以，就你的问题而言，物理模块的开销只能降低，而不能完全消除。 对于物理模块的开销，我们建议从宏观上进行了解，当你的项目完全没有使用物理模块时，那就需要从它的调用次数入手了。 Physics.Processing调用耗时： Physics.Processing调用次数： 可以看到，很多时候，该函数的CPU耗时其实并不是物理开销过高，而是调用次数过多。这主要是因为Unity 5.x默认设置的Fixed Timestep为0.02，Maximum Allowed TimeStep为0.333。也就是说，物理模块每20ms更新一次，所以如果某一帧很卡（200ms），那么物理模块会被调用10次，这样耗时就直接上去了。而0.333表示如果该帧CPU开销超过333ms了，那么就不会再调用物理模块，所以上图中调用次数中最大是17次。 所以，如果想进一步降低物理模块的开销，在完全没有使用物理的情况下，可以将Fixed Timestep设置为0.05或0.1均可，降低它被调用的频率。同时，尽可能优化其他模块耗时，让每帧的总体耗时尽可能降低。另外，需要注意的是，修改Fixed Timestep也会影响FixedUpdate的调用，在修改之前一定要检测项目中是否有使用FixedUpdate。 关于Contacts、Rigidbody、Collider的说明和推荐值，在UWA Tips中均有详细的说明。同时，也可查看如何读懂UWA报告——物理篇 。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/595351860ac5cef316b72ea1 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q2：Unity官方半透明Shader代码在iOS上运行出现问题，参考官方文档（https://docs.unity3d.com/Manual/SL-CullAndDepth.html）中Transparent shader with depth writes写了一个半透明的Shader，在所有iOS设备上都出现类似ZFighting的错误，在XCODE上看了一下，大致定位是深度写入/读取出现了问题。 正常情况 有问题的情况 环境如下： Unity4.7.1 f1 graphics Api opengles3.0 测试设备：iPhone5s、iPhone 6、iPhone 6s. 同样的代码在Android设备上没有问题。 ios设备上将Graphics API 设置为OpenGL ES 2.0 和metal在显示正常。 同样的代码在Unity5.3.8上graphics ApI OpenGL ES 3.0 编译到iOS设备上显示正常。 请问是什么问题导致的呢？ 第一个Pass预写深度，第二个Pass比较深度LessEqual，硬件差异以及图形API差异，是很难保证第二个Pass比较深度时Equal的。 是否可以手动设置一个深度偏移量来避免这个问题，相关文档可以参考： https://docs.unity3d.com/Manual/SL-CullAndDepth.html。 此问答来自于UWA 问答社区，目前题主反馈已经得到解决，特此感谢 jim 提供的回答。 https://answer.uwa4d.com/question/5951d21d96a4c14c505c478d 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q3：AssetBundle包字体bitmap A的使用到AssetBundle包Altas B时B冗余，比如我有个字体vip使用到betaCommon的altas。 然后betaCommon打成AssetBundle包。vip也打成AssetBundle包。但是 vip的AssetBundle包里面会包含betaCommon的png.这就造成了会有两份一样的png在内存中。 下图是vip的AssetBundle内容： 下图是betaCommon的AssetBundle内容： 根据研发团队提供的AssetBundle例子，已经复现了上述问题（我用的是Unity5.5.2版本），vip和BetaCommon两个AssetBundle确实存在冗余，其冗余度如下。 之所以出现冗余是因为vip和betaCommon两个Prefab实际上并没有建立其依赖关系（虽然mainfest上注明了存在dependencies）。所以，你的问题解决方式，只需要将BetaCommon Material设置为一个“显式”的AssetBundleName，那么冗余问题就不会存在了。 设置后，AssetBundle资源检测结果如下： 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/5950ed9d4477ba5f1121521a 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q4：Unity 5.x打包系统加载资源会出现两份相同内存吗？对此怎么理解呢？ 主要是针对unity5.x，特别是5.3.6版本。 我看其他博文上说是AssetBundle一份内存，然后LoadAsset又是一份，但是我看文档不是这样子的，AssetBundle那份只是一个配置信息，真正的内存是在LoadAsset的时候，希望UWA能为我们统一下理解。 理论上，内存是不会重复的，AssetBundle的内存和资源的内存是不一致的，特别是Unity 5.3版本以后。 在5.3.6版本上，加载一个LZ4格式的文件大小为5MB的AssetBundle，其内存是非常小，也就是经常看到的SerializedFile，该值根据OS的不同而不同，而最大不会超过0.5MB（每个AssetBundle内存占用）。AssetBundle.Load加载资源后，内存才会随着加载的资源不同而出现明显提升的现象。 具体的AssetBundle使用介绍，建议查看Unity原厂Manual网站，或者你应该知道的AssetBundle管理机制。 关于如何检测资源是否有重复，可以通过Profiler、 UWA资源检测与分析 和 UWA GOT 来进行查看。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/59545f97ce12979679229559 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q5：最近学习了UWA关于UI性能优化的直播，想问下切换UI场景使用AssetBundle加载慢，怎么优化界面进入速度，是应该预加载吗？ 一般来说，界面加载慢主要的原因有，图集纹理的加载以及大量UI元素的实例化操作。 针对图集的加载，可以尝试合理的规划图集，尽量控制界面所引用的图集数量（即使用到了某个图集中的一个Sprite，也会加载整个图集）；其次可以尝试对公共图集进行预加载，通常公共图集较大，且被使用的概率很大。 针对大量UI元素的实例化，这项开销大通常只发生在背包等复杂的界面中，而对于这类复杂界面可以考虑进行分步实例化，即首先实例化如外框、容器等部分的UI元素，然后分帧实例化背包中的UI元素，从而提高界面打开的速度以及流畅性。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）