UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - ngui
type: channel
link: https://blog.uwa4d.com/tag/ngui
items: NGUI Label 自定义材质球无效
items: URP下与Built-in的Light Color不一致
items: Unity引擎UI模块知识Tree
items: 如何大幅优化NGUI的堆内存分配
items: 高效的iPhone X适配技术方案（UGUI和NGUI）
items: 8.10 直播回顾 | 一个小时内，我们用UWA GOT解决了这些问题...
items: UWA 六月直播季 | 6.29 Unity UI模块中的优化案例精讲
items: Unity一键图集生成工具，附源码 (基于NGUI和TexturePacker)
items: 如何读懂UWA性能报告？—NGUI篇

NGUI Label 自定义材质球无效
type: item
date: 2022-05-10T05:03:00+03:00
description: 1）NGUI Label 自定义材质球无效 ​2）代码保存预制体出现图片丢失的问题 3）升级Unity版本，粒子系统触发的闪退问题 4）场景打包AssetBundle过大 这是第296篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） NGUI Q：想在NGUI下做一个字体溶解Shader，自定义的Shader材质球给Label不起作用，有没有大佬了解这块内容？ A：猜测题主是要在编辑器里面的材质球对象上调整_Threshold的数值，但在Game窗口发现文本没有发生变化。 本质原因是NGUI在对Label进行渲染的时候使用的并不是编辑器里面赋值的材质球，而是在NGUI进行合并DrawCall后动态创建的Material，所以我们需要对这个材质球进行材质球属性设置。 这里可以通过脚本来给实际渲染Label的材质球调整属性达到效果。以下分别是Threshold为0和Threshold为0.4的效果。 public class TestLabel : MonoBehaviour { public float threshold; public UILabel label; void Update() { if (label.drawCall != null) label.drawCall.dynamicMaterial.SetFloat("_Threshold", threshold); } } PS：这样处理的坏处是，和这个Label在同一个DrawCall的Label都会受到影响，所以需要将这些效果的Label的Depth做特殊处理，和其它的Label不放在同一个DrawCall中。 另外在NGUI的UI DrawCall脚本中，可以打开SHOW_HIDDEN_OBJECTS，这样在编辑器里面是可以看到生成具体的DrawCall对象，也就可以看到它们的材质球属性变化。 从下图可以看到具体的DrawCall，它的材质球名字会在前面加[NGUI]的字样，和编辑器里不是同一个材质球。 感谢Xuan@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/62480c7ea43e6117d050c8bf Script Q：我在Unity 2021.3.x上想根据配置动态生成预制体。现在遇到的问题是，可以把图片动态读取上去，然后保存预制体了以后，图片就丢失了，应该是需要修改.prefab里的值 。 我使用SerializedObject模块.objectReferenceValue去修改m_Sprite不会生效，它是引用类型的，而值类型的都是可以修改的。有大佬知道怎么修改嘛？ A：用下面的代码，是可以在编辑器里改的，不太确定楼主是不是想要在编辑器里操作，还是在Runtime下操作，理论上Runtime时是没有预制体的概念的。在编辑器里面，选中预制体，然后点击Update Prefab Asset按钮即可。 预制体很简单： public class Example { [MenuItem("Examples/Update Prefab Asset")] static void AddBoxColliderToPrefab() { // Get the Prefab Asset root GameObject and its asset path. GameObject assetRoot = Selection.activeObject as GameObject; string assetPath = AssetDatabase.GetAssetPath(assetRoot); Texture2D tt = AssetDatabase.LoadAssetAtPath("Assets/2.jpg", typeof(Texture2D)) as Texture2D; Sprite ss = AssetDatabase.LoadAssetAtPath("Assets/3.jpg", typeof(Sprite)) as Sprite; // Load the contents of the Prefab Asset. GameObject contentsRoot = PrefabUtility.LoadPrefabContents(assetPath); // Modify Prefab contents. contentsRoot.transform.Find("RawImage").GetComponen…

URP下与Built-in的Light Color不一致
type: item
date: 2021-01-13T04:08:00+02:00
description: 1）URP下与Built-in的Light Color不一致 ​2）开启MSAA的RenderTarget会对没开启MSAA的RenderTarget造成影响 3）角色Mesh合并的优点与缺点 4）NGUI渲染层级的原理 5）Unity上App图标安装到设备上图标模糊，设置上的注意点 这是第234篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Rendering Q：发现Light的Intensity在不为1的情况下，光照的颜色在URP下滑Built-in管线下不一致。附件里有2个工程，使用Unity 2019.4.11f1，分别是URP和Built-in管线的（都是线性空间）。（附件可戳原问答下载） 再现方法： 1. 打开2边工程的Scene1，这个场景的方向光Intensity值设置为1。观察2个工程里球的光照颜色，是一致的，通过FrameDebugger也可以确认这一点。 2. 打开2边工程的Scene2，这个场景的方向光Intensity值设置为0.65。观察2个工程里球的光照颜色，Built-in管线的更暗，通过FrameDebugger也可以看到Built-in管线的工程光照颜色数值小一点。 URP颜色： Built-in颜色： URP FrameDebugger： Built-in FrameDebugger： A：用楼主Demo里面的Light的颜色做了一下计算，在Light设置项里面，Light Color为（0，202，255），202.0/255 = 0.792。 SRP： Green通道： Mathf.GammaToLinearSpace(0.792) * 0.65=0.5906189 * 0.65= 0.383902285 Blue通道： Mathf.GammaToLinearSpace(1) * 0.65=1 * 0.65=0.65 Built-in： Green通道： Mathf.GammaToLinearSpace(0.792*0.65)=0.2280943 Blue通道： Mathf.GammaToLinearSpace(0.65)=0.3800563 应该是下面两段数值的计算区别： GammaToLinearSpace(m_ColorFilter * m_Intensity); GammaToLinearSpace(m_ColorFilter) * m_Intensity; 查询发现是由于GraphicsSettings.lightsUseLinearIntensity这个数值不一样导致的。在SRP里面这个数值是True，在Built-in里面是False。 感谢Xuan@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5fed681710a17c6c2b09d7db Rendering Q：在同一帧中，我有用于渲染的RenderTarget开启了MSAA，和用于热扭曲效果的扭曲Buff，是一张没有开启MSAA的RenderTarget，在后处理中这张扭曲Buff会用来偏移UV，以实现扭曲效果。在PC上和iOS上一切正常，但是在Android真机上出现异常。在高通GPU上，这张扭曲Buff会导致屏幕出现网格状的现象，在Mali GPU上会出现各种细碎的小黑方块，应该是一个未知原因导致扭曲Buff上的数据被处理成我不期望的状态。 如果我把其他的RenderTarget的MSAA关闭，这种现象就会消失，也就说开启MSAA的RenderTarget会对没开启MSAA的RenderTarget造成影响，且仅仅是在Android真机上出现，不同的GPU表现还不一样。有遇到类似问题的吗？求解。 A：该问题已经解决了。我所遇到的问题的最终情况，不是开启MSAA的RenderTarget会对没开启MSAA的RenderTarget造成影响。在开启MSAA后，主相机的RenderTexture（MSAA）绑定到Shader上，会有类似如下操作： texture(_Main_Tex, UV + Offset) 不知道是Unity的Bug还是其他原因，导致在Android真机上，绑定到Shader上的RenderTexture一定不是经过有效ResolveAA的版本，所以在如上操作的时候就出现异常表现，类似细碎方块或者网格等等现象，如果Offset是0，不会有异常表现，这些应该和Mobile GPU上的TBR有关系。 那么我需要在Android真机上传入一张经过有效Re…

Unity引擎UI模块知识Tree
type: item
date: 2020-06-11T10:53:00+03:00
description: 本文整理的内容会以UGUI为主，当然也会涉及到NGUI和FairyGUI的内容，并将UI框架和优化内容单列出来帮助大家分类学习，最后是UWA的工具篇，开发者们可以根据报告查看问题，优化项目。模块知识Tree内容会持续更新推送，本期推送在“优化”分类中新增了两篇课程《让UI性能飞起来-基于GPU实现的UI动画系统》和《UITookit下一代UI系统》。 在UWA学堂界面中的“分类“选择UI即可查看相关课程。 无论对于从业者还是正在读大学的技术萌新，学习的有效时间和个人时间都是有限的。高效学习者最在意的是时间的价值，一个需要体系化的知识地图就显得尤为重要。 UGUI 《UGUI开发基础与实践》 该课程通过对Unity引擎UGUI的基础介绍结合具体的实例制作，系统、详细地讲解了UGUI开发的各项实用知识点，主要包括：UI界面布局、自定义Shader效果、UI组件扩展、UI事件系统搭建，以及常用的性能优化方法等。 讲师会手把手带领学员掌握如何搭建高效和酷炫的3D UI系统，并在实践中理解其中涉及到的基础知识、运行机制，以及进阶技巧。 《UGUI深度研究之源码鉴赏》 从UI的代码底层讲起，通过理解底层代码的原理来认知上层的有效优化方法。这里会从源码中深入分析UI网格重建的实现原理，并完成了提取触发UI重建的UI元素的代码实现，可以更方便、更准确地定位引起UI性能问题的UI元素，从而有针对性地做优化。 而在分析Image、Text、Layout等部分源码的同时，也提出使用的注意事项。使开发者在UGUI制作及性能优化方面，更好地达到“知其然，知其所以然”的效果。 “UI开销如何优化？”、“如何定位引起重建的UI元素？”、“UGUI Text如何进行优化？”、“如何合理使用Layout？”、“在设置UI点击事件时有哪些注意事项？”等等这些常见的UI开发问题，都可以在这个专栏中得到解答。不管是行业新人，还是Unity从业者，都不妨来一起领略一番UGUI源码，相信都会有所收获。 《UGUI深度研究之优化技巧》 UI界面常常面临的性能问题是界面打开慢，在一些低端机上打开复杂UI时，可能会需要5秒以上。本篇专栏通过讲解纹理格式、纹理通道分离、纹理尺寸设置等方面，找到移动端UI纹理资源兼具效果和性能的合理格式，以此减少纹理资源加载耗时，从而减少UI的打开耗时。此外，还包括了UI制作上的常见UI制作优化思路，帮助开发者找到UI的“正确打开方式”。为了更好地在研发后期找到瓶颈UI，这里还提供了一个UI界面的静态分析工具，可以帮助开发者更直观地分析定位“问题UI”。 随着UI迭代和研发流程的变化，在UI资源上也会遇到一些不可避免的麻烦问题，本篇专栏也对这些问题进行了举例并给出了可参考的解决方案。 通过本篇专栏的学习，开发者可以更好地对移动端UI制作进行有条理的性能把控，提升UI界面的运行效率。 《Unity UGUI 渲染3D对象详解》 该课程是一个针对项目研发过程中一个场景问题的解决方案。在UI界面中渲染3D物体是一个非常普遍的需求，该课程讲解的并不是如何去渲染，而是讲解在UI界面中渲染3D物体通常会遇到哪些棘手的问题，它的原理是什么以及如何解决。通过该课程，你可以对UI界面中渲染3D物体的原理进行掌握，同时对于大多数研发团队中会碰到的问题和解决方案都会有一个更为全面的了解。 《Unity运行时动态图集的实现》 本课程讲解了Unity运行时通过动态图集来降低Draw Call的方法，从基本思路和实现原理切入，随后对动态图集的功能做了优化和扩展，附带Demo源码。不仅包含可复用的图集，还有空间利用效率更高的不可复用图集的实现。 《UGUI输入组件支持Emoji》 基本上每个游戏都会有聊天功能，策划通常也会要求我们支持Emoji的输入和展示。然而UGUI的InputField组件是不支持Emoji输入的，旧版本甚至输入Emoji还会触发exception。 本文会先说明为什么InputField不支持Emoji，这部分主要先解释一下Unicode的编码规则、计算机中Unicode的实现方式，再介绍Emoji的编码规则，以此推出InputField不支持Emoji输入的原因。 之后详细介绍一套低成本的解决方案，会逐个的说明InputField需要改写的关键点和原因，最后介绍Text组件对Emoji的渲染支持。 《详解UGUI Draw Call计算和Rebuild操作优化》 这是目前对UGUI Draw Call分析得最为透彻、全面的一篇文章。通过大量举例让大家直接明白为何UI界面中的Draw Call总是居高不下，同时让大家掌握对Draw Call、UI重建、Overdraw等高频实际问题的高效优化知识。 《Unity UI模块优化案例精讲》 对UI模块常见的…

如何大幅优化NGUI的堆内存分配
type: item
date: 2018-07-25T12:29:00+03:00
description: 目前，在Unity游戏项目中，依然有很多团队使用NGUI作为UI解决方案。相比UGUI，其临时堆内存分配过多始终是NGUI的一个缺点。本文旨在修改NGUI的几处底层实现，从而规避堆内存的临时分配。 文末，我们通过复杂的实例来对此方法来进行测试，通过比较可以看出，该方法可以大幅优化UI界面在运行时的堆内存分配。文章中对于NGUI解决方法的优化主要包括以下几个方面： 对UIGeometry的顶点属性做了缓存池，并保证OnFill时进行按需选择； 通过unsafe的方法来修改IndexBuffer的长度； 填充数组前充分设置List.capacity； 我们希望通过该篇文章，可以大幅降低您项目中NGUI的堆内存分配，以下则为具体的优化方法，大家通过具体的代码说明来进行逐一修改即可。 注意：所有本次优化相关的代码都用OPTIMISE_NGUI_GC_ALLOC宏区分开了，使用的NGUI版本是3.11.4。 UIGeometry的verts、uvs、cols、mRtpVerts缓冲池 UIGeometry记载了UIWidget的顶点信息，可以采用缓存池的策略，当UIWidget.OnFill的时候确定了需要顶点数量的情况下从缓存池申请，当UIWidget.OnDestroy的时候放回缓存池，回收的时候以顶点数量从小到大插入，申请的时候找到第一个满足需求顶点数量的。 缓冲池的实现 UIWidget.OnDestroy的时候放回缓存池 UISprite和UITexture我优化了三种类型：Simple、Sliced和Tiled。以下代码出现在UIBasicSprite.cs里，这里只贴了SimpleFill的完整实现，其他两个类型的顶点数计算部分有些区别： 以下是Sliced类型的顶点数计算部分： 以下是Tiled类型的顶点数计算部分： 因为上三个函数都可能在UIBasicSprite.Fill中给UIGeometry的几个List赋予新的实例，所以在UITexture 的OnFill中相关代码需要改成这样： UILabel.OnFill里额外提供了一个缓冲供NGUIText.Print使用，里面也考虑了UILabel带有描边和阴影时的优化。 NGUI创建Mesh时顶点索引缓冲的优化 从原来的顶点索引的生成算法来看，假设有一个顶点索引缓冲长度为9000，另一个有1w，那么这两个缓冲的前9000个索引的值是一样的，而且Mesh.triangles需要顶点索引缓冲的数量为顶点缓冲数量的三倍，所以最好是有个能够能动态调整Array.Length但Array的元素可以不发生变化的办法。 Nordeus在Unite2015上分享了一个VaryingList可以做到： https://github.com/Nordeus/Unite2015/tree/master/VaryingList 把BufferedList.cs和VaryingList.cs下载到工程，开启Unsafe就行了，它主要是通过Unsafe的方法来实现我们要的功能。这样，我们只需要一个顶点索引缓冲，而不是原来的10个，而且我们只在缓冲不够大的时候从新分配内存并只填充增加了的顶点索引缓冲，而当需要的顶点索引缓冲比当前的小的时候只需要通过Unsafe方法设置下长度就行了。涉及到的代码在UIDrawCall.cs中。 GenerateCachedIndexBuffer的修改 函数的替换 插入前充分设置List.capacity来减少GC Alloc 首先需要包装一下这个操作，List内部用GrowIfNeeded（相信同学们在deep profile里看过他很多次了吧）来进行扩容，我不想用反射，所以直接把代码拿过来用扩展做。 在UIPanel中，需要对FillAllDrawCalls和FillDrawCall进行优化，收集每个UIDrawCall对应的UIWidget和总的顶点数，然后一次性对UIDrawCall里的几个List一次性设置capacity。 UWA实测总结 针对优化的特点，UWA进行了以下测试，对比其在堆内存优化上的效果：首先依次隔帧创建以下面板，然后每隔100帧依次隔帧进行界面切换（从禁用变为激活，或者从激活变为禁用） 经过1000帧的测试，原始的NGUI累积分配了23.5MB的堆内存（左侧数据），而优化后的NGUI累积分配了9.7MB的堆内存（右侧数据）。 从数据中可见，把WriteToBuffers替换为FillDrawCallBuffers的优化是最为明显的，降低了约10.6MB，是原来的1/3；其次就是UIDrawCall:GenerateCacheIndexBuffer的优化，也下降了约2.5MB。 以上，则为作者对于NGUI底层代码的详细完善和优化，希望它可以…

高效的iPhone X适配技术方案（UGUI和NGUI）
type: item
date: 2018-06-12T11:16:00+03:00
description: 本文作者旨在通过改锚点的方式，分别实现在NGUI和UGUI上的iPhone X适配技术方案，并结合自身项目经验，阐述了主要的实现细节，希望能对广大游戏开发团队有借鉴意义。 适配来源： 按照苹果官方人机界面指南 ： https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/ 在iPhone X 异形屏幕上，苹果提出了Safe Area安全区的概念，这个安全区域的意思是，UI在Safe Area能够保证显示不会被裁切掉。 按照苹果的设计规范，要求我们把UI控件放在Safe Area内，而且不能留黑边。在Unity中就需要解决，怎么以更少的工作量把所有界面的控件停靠在Safe Area内，黑边的部分用场景或者背景图填充。 当我们横持iPhoneX的时候： iPhone X整体像素为2436 x 1125像素； 整体SafeArea区域为2172 x 1062像素； 左右插槽（齐刘海和圆角，再加一个边距）各132像素； 底部边距（由于iPhoneX没有Home键，会有一个虚拟的主屏幕的指示条）主屏幕的指示条占用63像素高度，顶部没有边界是0像素。 一、技术方案 1.改相机ViewPort 直接把UI相机的视口改为Rect(132/2436, 0, 2172/2436, 1062/1125)，然后把背景图设为另外一个相机。这样做的好处是，完全不用改原来的Layout。坏处是，多个UI的情况下，背景图和主UI之间的深度关系要重新设置。 2.缩放 把主UI的Scale设为0.9，背景图的Scale设为1.1，这样就能不留黑边。这个方法的好处是简单，坏处是会引起一些Tween已及Active/InActive切换之间的问题。 3.改锚点 分2种情况，NGUI和UGUI都有点不同。正好我都有2个项目的完整适配经验，所以才写了这个分享。 二、实现细节 首先我们拿到iPhone X 安全区域，Unity得开发插件OC代码来获取。SafeArea.mm拷贝到项目的Plugins/iOS目录中。 //获取iPhoneX safeArea //Jeff 2017-12-1 //文件名 SafeArea.mm #include <CoreGraphics/CoreGraphics.h> #include "UnityAppController.h" #include "UI/UnityView.h" CGRect CustomComputeSafeArea(UIView* view) { CGSize screenSize = view.bounds.size; CGRect screenRect = CGRectMake(0, 0, screenSize.width, screenSize.height); UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 0, 0); if ([view respondsToSelector: @selector(safeAreaInsets)]) insets = [view safeAreaInsets]; screenRect.origin.x += insets.left; screenRect.size.width -= insets.left + insets.right; float scale = view.contentScaleFactor; screenRect.origin.x *= scale; screenRect.origin.y *= scale; screenRect.size.width *= scale; screenRect.size.height *= scale; return screenRect; } //外部调用接口 extern "C" void GetSafeArea(float* x, float* y, float* w, float* h) { UIView* view = GetAppController().unityView; CGRect area = CustomComputeSafeArea(view); *x = area.origin.x; *y = area.origin.y; *w = area.size.width; *h = area.size.height; } 设计通用的适配component，哪些面板要适配，就直接添加这个脚本： using System.Collections; using System.Collections.Generic; using UnityEngine; /// //…

8.10 直播回顾 | 一个小时内，我们用UWA GOT解决了这些问题...
type: item
date: 2017-08-11T09:42:00+03:00
description: 昨天UWA技术直播间，UWA当家主播强哥再次强力圈粉，凭着备受粉丝认可的极具磁性的声音，过硬的技术实力以及在手上挥洒自如的的黑科技UWA GOT，UWA这次几乎将压箱底的绝招都公开啦！接下来，让这个视频告诉你UWA是怎么优化的吧！ PS：听说配合UWA GOT使用效果更佳哦！ 若观看模糊，请点击以下链接，在清晰度中选择高清。 视频源地址：https://v.qq.com/x/page/l0536uw71df.html 关于UWA GOT UWA GOT 全称 Game Optimization Toolkit，是由侑虎科技研发的本地性能测评工具。它既能方便研发团队在本地直接进行真机测试，也支持在Unity Editor中搭建本地服务器来接收和分析性能数据。整个测试过程中，研发团队能自定义测试时间和流程，几分钟后即可查看性能数据，同时还提供深度的数据分析，如脚本中的主要函数耗时、堆内存的具体分配堆栈等高级分析功能，从此为大家的项目性能又增添一份安全堡垒！ UWA GOT 目前提供 Performance Overview、Mono Memory Analysis 和 Runtime Asset Tracker三大功能。 往期直播精彩回顾 UWA 六月直播季 | 6.8 移动游戏加载性能和内存管理全解析 UWA 六月直播季 | 6.15 Unity引擎渲染效率全解析 UWA 六月直播季 | 6.22 Unity动画系统性能优化方案 UWA 六月直播季 | 6.29 Unity UI 模块优化案例精讲 昨晚，据说长得帅的人都在看直播！—NGUI性能优化篇（上） 驾驭NGUI，你需要了解的NGUI性能优化篇（下） 这些UGUI性能优化技巧，你被撩到了吗？—UGUI 性能优化篇 昨晚，直播间邂逅一股技术界的清流—UGUI 美术制作篇 UWA技术直播首秀精彩回顾（附视频）—性能优化案例精讲（六龙争霸 & 星辰奇缘）

UWA 六月直播季 | 6.29 Unity UI模块中的优化案例精讲
type: item
date: 2017-06-30T09:53:00+03:00
description: 昨晚，UWA两周年庆之直播充电月最后一弹《Unity UI 模块优化案例精讲》如约而至，UWA当红主播张强对UI模块中常见的性能问题进行了全方位解析，并从（1）如何降低界面的渲染开销和（2）如何降低界面的更新开销，以及避免峰值两个角度具体分析了UGUI和NGUI各自的优势和性能瓶颈所在，以及提升性能的主要方式。 性能优化是考究开发者匠心的，而UI优化更需要匠心中的匠心。以UWA的优化经验来看，90%的项目都在UI性能上存在不同程度的问题。为此，小编特奉上完整视频回顾，希望大家通过温故学习，对Unity UI模块的性能优化有个较为全面的把控。 若观看模糊，请点击以下链接，在清晰度中选择高清。 视频源地址：https://v.qq.com/x/page/e0520qxtjox.html 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 2）资源检测与分析 3）UWA GOT 三大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。

Unity一键图集生成工具，附源码 (基于NGUI和TexturePacker)
type: item
date: 2016-09-13T12:53:00+03:00
description: 很多项目都使用TexturePacker GUI打包管理图集，然后在项目中创建NGUI图集时，第一次需要手动操作。如果图集很多就需要做重复工作。笔者就想写个工具来批量完成，主要是为了提高工作效率。此文介绍了该工具的使用方法，并附上工具源码。 很多项目都使用TexturePacker GUI打包管理图集，然后到项目中创建NGUI图集时，第一次需要手动操作，如果图集很多就需要一直做重复的工作。笔者就想写个工具来批量完成，主要还是为了提高工作效率。下面介绍该工具的使用方法，文末附上了工具源码。 一、导入工具 注意：工具是基于NGUI的，因此在导入工具之前，请确保项目中已经有NGUI，不然这个过程中会报错。 导入成功后会看到： 工具是基于NGUI和TexturePacker GUI来打包和管理图集的，如果大家不了解TexturePacker GUI，可以参考https://www.codeandweb.com/texturepacker，网上也有使用教程。 用过TexturePacker（下面简称:TP）的都知道，TP打包图集会生成一张PNG图片和一个图集的配置文件。我这边使用时，直接把图片和配置文件导出到项目的某个文件夹下，如下图所示： 我选中UIAtlas文件夹后，就可以点击 UIFrameWork/ NGUI工具/ 批量创建RGB和Alpha分离的TP图集，然后就是等待。这个过程中会改变图片的格式、分离RGB和Alpha通道、创建材质、创建预制体，并把对应的数据动态挂载到预制体上。这些都不需要人工操作。 成功后我们会看到： 当然也存在一种情况：即只修改和更新某个单个图集。这时候再使用批量处理就没必要，也太浪费时间。那么，大家可进行如下操作： 二、不分离RGB和Alpha通道的TP图集的使用方法 和上面一样，只不过少了分离RGB和Alpha通道的操作，我就直接以下图来说明： 成功后如下图所示： 更新某个图集时，点击图片，然后选择对应的单个图集，创建方法就行。 三、直接用TP或者PS分离RGB和Alpha通道 那也没关系，只要为RGB和Alpha通道制定规则，把工具源码修改一下就可以使用。如果有需要，我后期可以加上这一块。 四、项目中经常使用美术字 如果还没用过美术字的可以百度 NGUI美术字 ，一般都是用BMFont小工具。 操作如图： 成功之后如下图： 单个更新的方法和上面操作一样。因为是展示，批量操作时就只用了一个图集，开发团队只要把所有的图集资源放在同一个目录下，然后批量处理就可以生成所有图集。 总结：工具的产生就是为了避免做重复的操作，提高效率。这是我项目中使用的工具，如果有考虑欠妥的地方，欢迎大家提意见或者自己根据需求修改源码。源码下载地址：https://github.com/henry-yuxi/NGUI_Tools 最后也希望大家乐于分享，让游戏行业的工作效率更加高效。谢谢！ 这是侑虎科技第101篇原创文章，感谢作者胡林超供稿。欢迎转发分享，未经作者授权请勿转载。作者QQ：342014463，博客：https://github.com/henry-yuxi。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。（QQ群：793972859） 同时，作者也是U Sparkle活动参与者哦，UWA欢迎更多开发朋友加入U Sparkle开发者计划，这个舞台有你更精彩！

如何读懂UWA性能报告？—NGUI篇
type: item
date: 2016-08-12T07:27:00+03:00
description: 前不久我们针对UWA报告中UGUI模块做过简介，不过鉴于依然有大量的开发商在用NGUI，UWA对其性能效率也提供了检测与分析。当然不同的UI实现机制，其对应的测评标准也各有不同，本期我们就来讲解如何查看NGUI相关的数据。 本系列为Unity开发者通读版，力求人人能读懂，建议阅读时间5分钟。 纸上得来终觉浅，绝知此事要躬行，www.uwa4d.com等你来体验。 抛砖引例 有别于之前家喻户晓的畅销大作，这次我们拿一个普通小清晰RPG游戏作为案例。在我们测试过的大量项目中，该游戏是少见的，以UI性能上位的。虽然这仅仅是第一次测试的数据，但是其在CPU耗时、堆内存分配上的表现都是甚如人意，瑕不掩瑜。 在UWA的报告中打开UI模块性能界面，大家就能看到如上图UI相关的详细参数。包括：CPU峰值、CPU均值、堆内存分配总值、堆内存分配均值。这里的CPU峰值取自以下4个UI函数的耗时总和。堆内存分配总值指测试过程中，这4个UI性能函数分配的堆内存之和。 UICamera.Update() 该函数通常在点击时出现开销。因此，当该函数的CPU开销较高时，通常都是因为调用了其他的较为耗时的函数引起。 UIRect.Update() 该函数通常在需要更新锚点位置时出现开销。因此，当该函数的CPU开销持续较高时，通常是因为当前场景中有较多的UI元素绑定了OnUpdate模式的锚点。 UIPanel.LateUpdate() 该函数为NGUI最主要的CPU开销，包含了对所有UI界面包括其下UI元素的状态更新、网格重建、DrawCall合并等操作。大量的UI变动或者不合理的UIPanel布局都有可能导致该函数出现较高的峰值。 UIRect.Start() 该函数主要涉及到UI元素的初始化操作，通常在UI界面被实例化时出现并产生一定的CPU开销。 报告往下看，是各个函数的具体CPU和堆内存开销。如果你对这些数据代表的数字是一脸懵逼的状态，不清楚是偏高了还是偏低了，请先打开右边的分析与建议。 如下图，红框内分别给出了四个函数的CPU占用详情，包括主体范围是多少，过高或过低。一般来说，我们建议堆内存总值控制在30MB内，如果可以，尽量再往20MB的极限靠靠。 在此，我们不妨点击某一帧，在底部查看该帧的CPU耗时。 上图中显示，在第5500帧时CPU的耗时为5.4ms，若要溯本求源，我们可以再去CPU耗时详情中定位是哪个函数引起的CPU开销。 如上图，我们看到这些耗时分别为： UICamera.Update(): 1.2 ms UIRect.Update(): 0.2 ms UIPanel.LateUpdate(): 4.0 ms UIRect.Start(): 0.0 ms (由于四舍五入) 通过这些具体的性能函数，以及这些函数的意义我们就可以大致做一个判断了。接下来就需要各位程序大大结合自己的UI设计具体问题具体分析了。由于此文的目的是为了帮助大家理解UWA性能优化报告，因而并不会大篇幅讲解NGUI性能优化的细则，下文先给一些比较通用的建议，可谓优化中的黄金法则！ 优化支招 1、 尽可能将静态UI元素和频繁变化的动态UI元素分开，存放于不同的Panel下。同时，对于不同频率的动态元素也建议存放于不同的Panel中。 2、对于UI元素，OnEnable和OnDisable都会进行较多的操作，因此即使不涉及到资源的加载，依然会有较大的CPU开销，因此，对于切换非常频繁的UI界面，我们建议更高效的做法是： （1）改变UI的位置（以UIPanel为单位）来实现UI的隐藏和显示，因为是位置移动，所以并不产生多余的CPU消耗，同时又可以节省Enable和Disable的CPU开销。 （2） 通过设置相机的Culling mask 来实现 UI 界面的隐藏和显示，同样避免Enable/Disable操作。该做法可能会一定程度地提高内存的开销（UIDrawCall中存储的Mesh），因此可以根据UI切换的频率来决定是否要进行优化。 3、UI资源进行详细检测，查看其分辨率、格式等是否足够精简和优化。 今天的分享就到这里，下一期我们会继续讲解UWA测评报告中的内存模块，感谢各位开发者的关注。