UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - 技术分享
type: channel
link: https://blog.uwa4d.com/tag/技术分享
items: UWA DAY 2025 正式启动｜十年筑基，驱动游戏未来引擎
items: 关于Unity UI的动静图集分离，你需要了解这些！
items: 技术分享连载（六十五）
items: 技术分享连载（六十四）
items: 技术分享连载（六十三）
items: 技术分享连载（六十二）
items: 技术分享连载（六十一）
items: 技术分享连载（六十）
items: 技术分享连载（五十九）
items: 技术分享连载（五十七）

UWA DAY 2025 正式启动｜十年筑基，驱动游戏未来引擎
type: item
date: 2025-04-24T06:43:00+03:00
description: 由侑虎科技UWA主办的年度游戏开发者大会 - UWA DAY 2025，正式拉开帷幕！作为第八届盛会，也是侑虎科技成立十周年的里程碑之作，本届大会将以“十年筑基 · 驱动游戏未来引擎”为主题，于2025年8月在上海盛大举办。 从开发优化到质量保障，从前沿技术到实践落地，UWA DAY始终紧贴行业脉动，持续为开发者提供深度技术交流的平台。今年，我们将以更加开放的姿态，与广大开发者共同探讨下一阶段游戏工业的进化之路。 十年耕耘，与开发者共筑技术星河 自2015年创立以来，UWA始终坚持“快｜精准｜有温度｜值得信赖”的初心，持续深耕游戏研发工具和服务。十年来，从性能评测工具到全生命周期解决方案，从小型沙龙到全国技术峰会，我们始终与开发者并肩前行，见证并参与了中国游戏产业的不断跃迁。 UWA DAY，作为技术交流的风向标，也在这三千多个日夜中与千万开发者一起成长。站在十周年的新起点，我们愿以更加坚实的技术底座，为下一代引擎注入持续动力。 技术破界，重构未来研发生态 本届UWA DAY将围绕「引擎革新」、「工业化工具链」与「研发生态建设」三大核心主题，来自UWA及行业顶尖团队的资深技术专家，预计带来30+场高质量分享内容——从理论探索到实战落地，绘制一幅面向未来的技术图谱。 议题议程 2025年8月1日 周五 2025年8月2日 周六 议题总览 ➨十年筑基，驱动游戏未来引擎 主题演讲 张鑫 侑虎科技 CEO 随着移动游戏研发成本持续攀升与轻量化游戏生态的成熟，中国游戏行业正呈现 "品质深耕" 与 "敏捷开发" 并行的双轨发展格局。一端是3A化手游对工业化流程的极致打磨，另一端是轻量化团队对快速迭代效率的不懈追求。这种行业分化既考验着UWA技术服务的专业性与适配性，也为工具矩阵的场景化创新开辟了全新赛道。 过去一年，UWA围绕研发效率与玩家体验两大核心场景展开深度探索，在技术落地与产品迭代中实现关键突破。本次报告将重点分享三个方向的成果： GPM 2.0：玩家端体验的精准洞察。通过精准捕捉玩家的性能异常波动，为高品质游戏的长线运营提供质量保障。 GOT Online & Pipeline：工业化流程的 AI 赋能。通过与AI大模型的结合，进一步降低游戏团队对于研发工业化流程的准入门槛。 Gears：降低研发端性能检测的使用门槛。通过这一年来不断完善的检测功能，满足广大游戏团队的日常常规检测需求。 行业变革之下，UWA 始终相信，唯有扎根研发痛点的持续创新，才能在品质与效率的双螺旋中找到平衡点。本次报告将深度拆解技术落地的实战经验，期待与行业同仁共探 "工业化流程+智能化工具" 的破局路径，以十年积淀为基，为游戏未来研发注入新的动能。 ➨ UWA Gears深度体验 - 运行时性能测试与GPU深度分析新突破 张强 侑虎科技 CTO UWA Gears作为一款集成运行时性能分析与截帧渲染分析的专业测评工具，是游戏GPU性能优化的重要支撑，能够为开发者提供精准的性能数据与问题定位依据。 当前，随着游戏引擎对Vulkan API的支持日益成熟，以及移动设备的快速更新换代，Vulkan的兼容性持续改善，其在渲染效率提升、图形资源内存优化等方面的优势逐渐凸显，越来越多的研发团队开始使用Vulkan。在此背景下，UWA Gears近期实现了对Vulkan API截帧分析的支持，为开发者在Vulkan环境下的GPU性能优化提供了更强助力。 本次报告将围绕UWA Gears展开分享：一方面，详细演示如何借助该工具进行GPU性能分析；另一方面，重点展示在Vulkan环境下的重要参数解读与分析方法。通过这些内容，助力开发者更透彻地理解Vulkan特性，精准发现并高效解决GPU性能问题。 ➨ 虚幻引擎5构建开放世界下的优化、挑战以及开发方向 陈宝康 Epic Games 开发者关系工程师 现担任Epic Games开发者关系工程师，协助解决游戏公司在使用虚幻引擎中遇到的相关问题，曾先后就职于字节、腾讯，从事游戏开发多年。 随着引擎技术的不断发展，游戏引擎未来会更加关注开放世界的构建能力来带给玩家以沉浸式的体验，而Epic作为以赋能创作者和构建数字生态为核心的商业引擎，长远目标同样也是为了创建出一个元宇宙的虚拟世界，并带给玩家以身临其境的体验。每个人都可以自由的进行创作和表达，构建虚拟世界的未来，同时并将其技术赋能于游戏、影视、工业等不同领域。而在这长远目标下如何去构建开放世界成为了其中的重要一环，因为构建开放世界下的场景对游戏引擎提出了更高的要求，更大的开放世界意味着制作过程中需要面临一系列问题，本次报告与大家分享的就是虚幻引擎5针对开放世界在不同版本中主要做了哪些工作、目前的进度、面临了哪些挑战，以及未来的开发方向。主要包括：UE5构建开放世界的技术点、不同版…

关于Unity UI的动静图集分离，你需要了解这些！
type: item
date: 2018-03-06T03:39:00+02:00
description: 本期我们聚集了这些话题：UI 图集静态分离、Unity烘焙问题、Unity渲染异常、Animation.RebuildInternalState......(UWA一下，你就知道~） 这是第101篇UWA技术知识分享的推送！（此处应有掌声）随着大家在UWA平台上的发言愈加活跃，我们也源源不断地收到了许多技术大咖的热心回复和真知灼见。 UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） UI 管理 Q1：对于Unity的静态图集和动态图集分离，我有些疑问。我们UI制作方法如下： Prefab (UIHero) Prefab的静态图集 (UIHeroAtlas) Prefab上可能的动态图集 (UIHeroIcon) 如头像 生成的Bundle： Prefab一个bundle,它包含了静态的图片 动态图集一个Bundle 后来，为了能动态合批减少几个DrawCall，可能静态图集上有2-3张图片，在动态图片的上面当一个小边框背景。然后美术想把它放到动态图集，这样图片重叠时，它和动态图集的图也会是一个DrawCall。 我们的问题是：在使用AB的方式加载这个UI-prefab时，会不会加载整个动态的图集（UIHeroIcon）呢？还是说不会加载整个UIHeroIcon，只是把这两个静态图加载，动态UIHeroIcon照样不会加载？这种方式是否会造成热更新UIHeroIcon动态图集后，导致UIHero-prefab无法加载这两个静态图片的情况？那么我该如何取舍？ 1.会不会加载取决于你，Unity只是给出依赖列表，是否加载自行控制。 2.不会加载整个UIHeroIcon。 3.这里差不了几个DrawCall。而前景可能有很多种，美术的方案不一定通用，以后可能会拆回来。我的理解是，是静态图集中有2个Sprite A和B，然后在动态图集中也复制一份A和B。重叠时，如果UI深度不同，不一定可以合并。资源结构为重，不然之后维护会很麻烦。 感谢UWA问答社区 @史云柯 提供了回答 UWA补充：补充下史云柯回答中的第三点，建议评估下DrawCall能节省多少。举个例子，如果是个10人MOBA，那么在团战过程中10个Icon可能是叠在一起的，由于图集穿插就有可能增加到20个DrawCall，对于中低端设备节省20个DrawCall的话，性价比还是可以的。如果最差情况也就10个不到，那么确实性价比不高了。 此问答来自于UWA 问答社区，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a94dd200b827e2c0bfdd022 渲染 Q2：请问各位Unity5.3烘焙得到的LightingData.asset、Lightmap-0_comp_dir.exr、Lightmap-0_comp_light.exr各有什么作用呢？打包和加载的时候实际上是用了哪一个文件，还是全都需要？ UWA：LightingData.asset的介绍可以看这两个文档： https://docs.unity3d.com/Manual/LightmapSnapshot.html https://answer.uwa4d.com/question/5a4f4367e041ef3c50c9ce64 简单说，这里面存的就是场景中各个受Lightmap影响的物件的相关信息，Editor下这个文件可能会很大；但真机上，在不使用precomputed gi的情况下这部分的数据打包到手机上应该是很小的（毕竟对于一个物体来说，主要的Lightmap信息就是lightmapIndex和lightmapScaleOffset）。 另外，这部分信息是和场景文件绑定的，不能单独管理。所以默认情况下，Lightmap只能随场景一起加载。如果需要动态加载lightmap，可以参考这篇文章：http://www.xuanyusong.com/archives/3807；而后面两个.exr文件就是储存光照信息的纹理，_dir是光的方向信息，_light是光强信息（最简单的模式下只需要这一张）。这些文件是运行时需要的，不过exr是支持HDR的格式，在手机上会默认转成其他格式的，大小与exr是不同的。 该回答由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a9a69720b827e2c0bfdd0a7 动画系统 Q3：Camera.Render里面Animation.RebuildInternalState耗时较多，调用比较频繁，这个主要是哪些情况会调用呢？ UWA：之所以出现这一项，主要可以说明一下两点： （1）题主项目用的是Ani…

技术分享连载（六十五）
type: item
date: 2017-05-22T16:56:00+03:00
description: 本期聚集话题：优化PutGeometryJobFence耗时、CanvasRenderer.OnTransformChanged、UGUI渲染耗时定位、Clear 开销优化... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 性能优化 Q1：在UWA性能报告中，看到PutGeometryJobFence开销较高，请问这个该如何进行优化？ 就目前我们所优化过的项目而言，推测PutGeometryJobFence是Unity项目的主线程在等子线程的一些网格计算操作完成，其在不同的模块中均有出现（UGUI模块、渲染模块、Mesh.Skin操作、Animator动画模块等等），出现的地方不同，其本身含义也并不相同，不能一概而论。 而就上图中的耗时来看，如果项目中使用了UGUI，那么很大几率（>80%）是由于UI模块的不合理操作所致。我们在Unity5.3~5.5版本中深度优化了多款手游，均不同程度地遇到了该值耗时较高的问题，并且该函数与WaitingForJob经常成对出现，特别是在Android平台上。 下图为一款我们深度优化的ARPG项目中，PutGeometryJobFence在游戏运行时的耗时开销。 通过现场进行定位，我们发现PutGeometryJobFence的开销，实际上是主线程在等子线程中的耗时完成的等待时间，且几乎全部是等待Canvas.GeometryJob，如下图所示。 因此，我们直觉猜测该UI模块的重建开销很高，以至于子线程的计算压力过大，而PutGeometryJobFence较高，也很可能是主线程的等待时间。为了验证这一猜测，我们开始大力定位和优化该项目的UI模块的重建开销，待调整和优化项目的UI模块后，其WaitingForJob的运行时开销大幅降低（接近于0ms），而PutGeometryJobFence的CPU耗时则基本上可以忽略不计了。 同时，需要说明的是，以上仅是我们目前在多款Unity5.3~5.5项目中的具体优化经验，但并不能说明PutGeometryJobFence耗时高就一定是由UGUI模块导致，随着Unity引擎的不断升级，其背后也会隐藏着更多的含义。因此，希望大家在优化时就具体问题进行具体分析、具体解决。 性能优化 Q2：下图中，函数"Transform.set_position"的开销很大，请问有办法优化吗？ 从图中看，是通过Deep Profiler进行的函数耗时统计，首先Deep Profiler本身对于耗时的统计影响很大，通常在Deep Profiler下调用次数越多的函数，其耗时的统计就会越明显地偏高，因此，我们首先建议关闭Deep Profiler，同时用Profiler.BeginSample/EndSample将修改Position的代码包进来，再查看其耗时，相对会更加准确。 其次，可以观察到有180次的CanvasRenderer.OnTransformChanged的回调，移动UI元素相比于移动其他的元素确实会有额外的开销，建议减少不必要的UI元素的移动，比如通过增加移动阈值，降低移动频率等等。 性能优化 Q3：Unity Profiler中的Canvas.RenderSubBatch是否属于UI上渲染的开销？和重建有关系吗？ 这个确实是UI模块（UGUI）的渲染开销，但是跟UI的重建并无太大关系，主要还是跟UI界面的渲染Draw Call相关。从上图中可以看出，UI Draw Call达到45个，该值较高，研发团队渲染对UI模块的Draw Call进行进一步优化。 性能优化 Q4：这个Clear的耗时为什么这么大，有什么可以优化的方法吗？ 图中的Clear耗时确实很高，但需要研发团队关注该高值是小概率出现，还是经常出现。如果是前者，则无需过分担心，但如果是后者，则需要研发团队关注相机图像后处理操作的使用。Clear操作一般是用来清除Camera的各种Render Buffer，当图像后处理使用的越多，则同一帧中开辟更多的Buffer的概率也越大，从而造成Clear的开销也较高。对此，如果你的项目中Clear耗时较高，且高耗时较为频繁，则建议先关闭图像后处理操作，来查看该情况是否有所好转。然后再逐步开启各个图像后处理操作，逐步定位造成Clear较高的耗时根源。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，…

技术分享连载（六十四）
type: item
date: 2017-05-16T04:33:00+03:00
description: 本期聚集话题：Shader Variant Collection、如何优化Material.SetPassFast、粒子资源的AssetBundle打包方式... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：465082844 UWA 问答社区：answer.uwa4d.com 资源管理 Q1：Unity 5 的 Shader Variant Collection 功能是否推荐使用？我有以下3个疑点： 1）使用 Shader 变体之后，Shader 是否还能走资源更新？抑或 Shader 不推荐走资源更新？ 2）Shader 变体和 Shader Always Include 的主要区别是什么？二者对内存和帧率影响如何？ 3）在 Unity 5 较早的版本中，Shader 变体功能似乎有一些Bug，现在是否可靠？ 经过测试，在较新的版本中（如Unity 5.5.3），将ShaderVariantCollection与Shader打包在相同的AssetBundle中后，其中会包含该Shader在ShaderVariantCollection中指定的Variant。因此： 1）使用 ShaderVariantCollection后依然可以进行资源更新（通过更新AssetBundle，来更新Shader的实现或者ShaderVariantCollection中包含的Variant）。 2）ShaderVariantCollection与Always Included Shaders的区别主要在于打包时所包含的Variant。Always Included Shaders中的Shader，其所有的Variant都会被包含，好处是，理论上不会出现Variant丢失的情况；坏处是，会导致更大的发布包以及额外的内存占用，而影响最大的是手动进行Warmup时的耗时以及ShaderLab的内存占用。因此一般来说，对于Variant特别多的Shader（如Standard Shader），并不推荐放入Always Included Shaders中。 3）目前即使是较新的版本，其可靠性我们也并不能确保，依然建议在使用前进行一些测试来验证。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/591418087640b5a822204e73 如您对该问题仍有疑问，可以转至社区进行进一步交流。 性能优化 Q2：请问为什么我项目渲染中Material.SetPassFast的开销这么高？这个该如何优化？ Material.SetPassFast是Unity引擎在渲染过程中Material的轮循切换开销，一般在Unity5.0~Unity5.3版本中出现。它的开销主要分为两种： 1） Shader.CreateGPUProgram峰值开销 这种情况主要出现在Shader第一次渲染时。在Unity5.0以后，引擎为了避免Shader加载时过高的CPU峰值出现，已经将Shader.Parse和Shader.CreateGPUProgram两种操作分开执行，前者在Shader加载时，后者在Shader第一次渲染时。下图则为一款项目运行时渲染时的Shader.CreateGPUProgram开销。 2） 渲染状态切换开销 这种情况是几乎每一帧都发生的，有渲染的地方就会有Material的切换。从问题图中可以看出，在运行的16000帧中，Material.SetPassFast一共被调用137万次。这里可以认为几乎全部是渲染时Material的切换操作。因此，该项较高的主要原因还是材质切换操作过多所致。所以，建议研发团队在报告中的详细材质页面查看是否有过多“冗余”的材质出现，如有则尽可能降低材质的使用冗余度。 动画 Q3：Animator会把所有状态的AnimationClip加载到内存，有什么好的办法可以动态加载？ 1）Animator Controller结构不需要改变，但动画需要变化。比如随着人物等级或技能升级，同种的攻击动作随着变化等。该种需求可以通过AnimatorOverrideController来进行完成，即按需加载新的AnimationClip，然后替换AnimatorOverrideController中相应的AnimationClip即可。目前，Unity的AnimatorOverriderController不仅可以进行单个替换，同时也可以ApplyOverrides成组替换； 2）Animator Controller结构需要改变，类似于Animation老版本动画的AddC…

技术分享连载（六十三）
type: item
date: 2017-05-09T10:17:00+03:00
description: 本期我们聚集了这些话题：UI 血条制作方法比较、Unity5.6 Lightmap中渲染高光、Mono堆内存机制、动画精度优化... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com UI Q1：我在改血条，我原来是一个Canvas里放了所有血条，后来改成每个血条一个Canvas，再改成每个血条完全不用UGUI，直接用SpriteRenderer绘制，感觉性能越来越差了，怎么办呢？ SpriteRender的使用确实非常少，目前我们对SpriteRender的合并性能也还没有进行过测试，无法分析其底层的合并机制和开销细节。这里仅对于“所有血条放一个Canvas”和“一个血条放一个Canvas”做一个比较： 1）前者的开销主要在于网格的更新，在Unity5.2之前，可以从Canvas.BuildBatch中看到，而之后则主要是在子线程中通过Timeline来查看。因此只看主线程的话，这种方法肯定是更高效的； 2）后者的开销主要在于DrawCall的数量（前者理论上能做到只用1个DrawCall，后者一个Canvas即一个DrawCall），开销被包含在了Camera.Render或者Canvas.RenderOverlays中，在中低端机型上，100个DrawCall的开销也是很明显的； 因此，在选择时，需要考虑的就是“网格更新”和“DrawCall”的权衡，比如：如果一个血条的顶点数只有8个，100个血条也才800个顶点，而800个顶点的网格更新开销是明显低于100个DrawCall的；但如果血条的顶点数很高，那么就需要考虑拆分Canvas，尽可能做到某些Canvas是间歇性静止的，从而降低一部分网格更新的开销，但如果所有的血条每帧都会移动，那么拆分Canvas的效果也不会太明显。 总之，还是建议尽可能降低血条的顶点数，然后选择前者。 图形渲染 Q2：请问下在Unity 5.6版本中如何解决预渲染缺少高光的问题？该版本中光照预渲染Directional Mode选项中少了Directional Specular选项，渲染出来的效果场景缺少高光。 现在Unity 5.6的Lighting面板如图： Unity 5.6的确是将Lightmap中的Directional Specular选项去掉了。如果需要在使用Lightmap时渲染高光，替代方案是采用Mix Lights模式下的Shadow Mask以及Distance Shadow Mask选项。即将场景中的Directional Light改成Mix Lighting类型，并且在Lighting Mode选Shadow Mask或者Distance Shadow Mask。其原理是：LIghtmap中仅仅存储indirect的光照，而direct光照是实时计算的，所以包括高光、阴影等都可以是实时的（阴影也可以是预计算好的）。这样做的好处是给Lightmap光照一定的灵活度，原来的Lightmap是完全静态的，现在是部分静态（direct的实时，indirect静态）。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/5902db1da7fbeb4a58bf64a3 如您对该问题仍有疑问，可以转至社区进行进一步交流。 骨骼动画 Q3：我把骨骼文件的Optimize Game Objects”开启了，然后骨骼信息就没有了，那Avatar换装时候需要处理的骨骼信息怎么办？ 在开启“Optimize GameObject”选项后，因为Avatar信息消失，所以并不能通过原始的合并骨骼、合并Mesh的方法再来实现换装功能。对于开启“Optimize GameObject”选项的模型，Unity本身有另外一套更为方便的换装方式，即只要所换装模型的骨骼结点信息与Avatar自身骨骼信息可以匹配，那么直接将换装模型挂在Avatar模型下做为子节点即可，而不必再通过骨骼合并的方式来进行换装。 内存管理 Q4：Unity的Mono在内存不够的时候GC操作是即时触发的吗？比如说我当前Mono总内存是20MB，已用15MB（其中5MB可回收），然后我同步加载大量资源，需要9MB内存，Mono上限可能被撑大？ 按照问题的描述，Mono内存并不会撑大。一方面，如果加载的9MB内存是来自于资源，那么资源内存是不属于Mono内存，Mono内存是逻辑脚本所产生的堆内存。另一方面，如果这9MB是来自于堆内存，那么也未必会引起Mono上线撑大，因为Mono在堆内存不够用时，会先触发…

技术分享连载（六十二）
type: item
date: 2017-05-05T10:45:00+03:00
description: 本期聚集的话题：Static Colider.Move性能开销、耗电发热该如何优化、Resources加载和AssetBundle加载的区别、渲染模块中的Mipmap设置 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 资源管理 Q1：在Unity 的 Profiler里，有些记录右边会有Warning的个数信息，请问这个是否影响性能，或者是否有必要修改呢？ 这种字符的出现很可能会导致后续的物理更新出现较大的性能开销，包含在Physics.Simulate/Processing中。出现这种情况主要是受限于Unity版本中的PhysX在移动静态碰撞体是开销较高的问题（虽然文档中说5.x下已经解决，但我们确实发现在5.x的项目中该项仍然存在）。因此，我们建议给需要移动的Collider加上RigidBody并勾选Is Kinematic复选框，从而将其变为动态碰撞体，如下图所示。对于不移动的物体，则直接将模型的Apply Root Motion选项进行关闭，从而直接省去Static Collider.Move的性能开销。 资源管理 Q2：我们设置了TargetFrameRate为30，想避免过高的耗电和发热，请问这样做是合理的么？ 这种设置仅在帧率本身很好的情况下，才会起到减少耗电和发热的作用。但如果本身游戏已经较为卡顿，那么该设置方法意义不大。对于耗电和发热，研发团队需从CPU、GPU和IO入手，尽可能降低这三方面的负载压力，比如： （1）CPU：针对UWA性能测评报告中的Top10函数进行优化，根据性能堆栈定位性能根源并进行优化； （2）GPU：针对报告中的OverDraw对GPU负载较大的根源进行完善和优化； （3）IO：尽可能控制资源加载的粒度和网络传输的频率。对于资源粒度的划分，我们曾有过较为深度的分析：可以参考《技术分享连载五十九》。 图形渲染 Q3：我们美术在制作场景地面的时候，会有如下图所示的非常明显的一条模糊和清晰的分割线。我清楚这是由于Mipmap的使用导致的，我们不想让这条线这么明显，初步的想法是设置Texture的mipMapbias这个参数，这个参数没有在Texture的配置界面上提供。 Q3.1：想问下Unity有没有办法全局设置这个值？或者只能像我们现在这样在贴图导入的时候由脚本来设置？官方给的这个值的建议是“Note that using large negative bias can reduce performance, so it’s not recommended to use more than -0.5 negative bias.”，按照我之前的理解，这应该对应到Mipmap偏移层数的设置，应该是个整数。 目前来说我们没有发现能全局设置的办法。 Q3.2：不清楚这个建议不超过-0.5的值具体含义是对应几层Mipmap偏移？ Mipmap的层级数的确是一个整数。mipMapbias是由Unity引擎定义的一个参数，按照Unity官网解释来看整数代表了比当前层级更低（级数更大，更模糊）的Mipmap，负数代表了比当前层级更高的Mipmap。“-0.5”具体是偏移多少层级目前也不是很清楚。 Q3.3：我们也尝试了Trilinear的Filter Mode设置，并没有明显的效果，按理说这个设置应该是会让Mipmap采样两层中的8个点进行混合，这点也有点奇怪。 Trilinear应该是会比Bilinear效果好一些，但是也差强人意。原因是这样：传统的Mipmap（不采用Anisotropic Filtering）都是每层将u，v两个方向缩减一半，即：512x512的下一层是256x256。这就导致在两层交界处在不同层采样出来的纹理在u，v两个方向都被拉伸（或者叫变模糊）。Anisotropic Filtering的方式可以简单理解为在交界处只在某一个方向上被拉伸，另一个方向保持原有采样率（或者叫纹理分辨率），这样才能明显降低突变的模糊感。 Q3.4：目前我们给美术的建议是使用Aniso Level，调整一个比较高的值，比如大于6，会有比较理想的效果，但是查了一下这个的性能消耗貌似很大，不知道UWA有没有对这个参数做过性能的分析，具体的性能消耗有多大？ 使用Anisotropic Filtering不仅纹理内存占用会增高，而且采样率也增高（因为有一个方向的保持不变），因此它比传统的mipmap更耗时，耗时在于GPU端对纹理进行采样时增加了访存，在CPU端没有影响。虽然Anisotropic Filtering 耗时…

技术分享连载（六十一）
type: item
date: 2017-04-25T06:31:00+03:00
description: 本期我们聚集了这些话题：优化Shader预加载、 MMO游戏资源规范、GC分配定位、Unity的普适性的资源管理问题... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 资源管理 Q1：Unity5.4.1中，我将需要的Shader打到一个AssetBundle包中（包含一个关联了所有Shader的Shader Variants），分别用Shader.WarmupAllShaders和ShaderVariantCollection.WarmUp两种方式进行预加载，后者耗时更少。 这里用了Standard Shader做的测试，可以看到真机上两种方式耗时差距是非常大的。 请问，确实是ShaderVariantCollection的效率更高，还是我测试方法有问题？ 测试代码： Shader的AB包里的内容: 根据官方的文档的描述，确实是ShaderVariantCollection的效率更高，详见： https://docs.unity3d.com/Manual/OptimizingShaderLoadTime.html 因为在ShaderVariantCollection中，是可以给每个Shader添加指定的Keyword的，ShaderVariantCollection.WarmUp的调用只会对ShaderVariantCollection中指定的Keyword进行Warmup操作；而Shader.WarmupAllShaders则是对所有的Keyword全部进行Warmup操作（其中大多数很可能都不会用到）。 因此在Shader.WarmupAllShaders的文档中也提到，建议使用ShaderVariantCollection.Warmup来进行细粒度的Warmup操作，避免大量多余的Keyword被Warmup，造成严重的卡顿，大家可以参考下文： https://docs.unity3d.com/ScriptReference/Shader.WarmupAllShaders.html 此问答来自于UWA 问答社区：https://answer.uwa4d.com/question/58fabe919db5d16c66166132 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q2：我们在做MMO国战类游戏，因此想咨询下资源标准。我们同屏会有70~80个玩家，这种情况下主角一般控制在多少面，多少根骨骼呢？一个Boss有80多根骨骼会有问题吗？ 这个需要看研发团队希望在什么样的机型上运行。假设是低端机器类似红米Note2，那么建议玩家都控制在30根骨骼，1500面以下。如果只有一个怪物80根骨骼，问题并不大，但还需要考虑场景中其他物体的使用量。 建议研发团队看一下这篇文章，这是我们半年前统计的关于MMO游戏的性能数据，相信能对MMO游戏的开发团队具有借鉴意义：《MMO移动游戏性能分析报告：渲染、UI、逻辑代码和内存需重点关注》 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/58f614999db5d16c66166121 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q3：我们想请教一个Unity的普适性的资源管理问题。举个例子，我们现在的一个特效Prefab包含的贴图打成AssetBundle时没有单独拆分出来，就会存在一个问题，这个特效AssetBundle会存在重复加载的问题进而导致重复的特效贴图在内存中。（针对“重复加载”说明下：我们首先通过AssetBundle出来一个Object，这个Object会缓存一段时间，在这段缓存时间过后这个Object会被Destroy掉，而需要释放的特效是通过Instantiate这个Object出来的。当这个Object过了缓存时间被destroy掉后，下次需要释放相同的特效还是通过load同样的AssetBundle进行再实例化出来，这样内存中存在两份贴图了。） Unity中是没有这种API来提供的，一般是团队中自行做一些资源的引用计数来进行管理。频繁调用UnloadUnusedAssets是不可取的（该函数的主要作用是查找并卸载不再使用的资源。游戏场景越复杂、资源越多，该函数的开销越大，一般在300~2000 ms范围内），但可以调用UnloadAsset来释放资源。 内存管理 Q4：我们游戏现在测试出来的GC是否合理？这个分配数值可以接受吗？是否存在泄露？如果存在泄露，有没有具体到每个函数的分配详情？ 研…

技术分享连载（六十）
type: item
date: 2017-04-17T13:11:00+03:00
description: 本期我们聚集了这些话题：LoadFromCacheOrDownload使用规范、编辑器下字体引用、网格的顶点色渲染... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 资源管理 Q1：对于WWW.LoadFromCacheOrDownload(System.String url, Int32 version)这个接口的第二个参数，我知道是做缓存资源的更新用的。我们之前在Editor模式下作了一个测试：用该函数加载一个资源，Version参数设置为1，会发现在缓存目录下生成了一个对应该资源的缓存目录，这很正常。然后我们再次用这个接口加载这个资源，Version参数设置为2，现会发在缓存目录下生成一个新的对应该资源的缓存目录，并没有覆盖旧的目录。这个情况在移动平台上是否也是这样的？ 是的，在移动平台上，通过LoadFromCacheOrDownload加载的AssetBundle，其Version版本号变化时，新的解压Data是不会覆盖旧的解压Data的。清除旧的解压Data主要有三种方式： 设置缓存的过期日期，默认情况下是150天； 调用Caching.CleanCache来全部清空缓存； 当本地Cache已满时，Unity会从最早的AssetBundle来进行自动清理。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/58ec4adfda71c21b3b1ac91f 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q2：我听说WWW.LoadFromCacheOrDownload(System.String url, Int32 version)这个接口加载资源，如果是Unity 4.x的版本，会有500个资源的数量限制，如果超过这个限制，Unity会删除之前缓存的每个资源，是这样吗？那在Unity 5.x 版本上是否还存在这样的问题呢？ 在Unity 4.x的版本中，如果通过LoadFromCacheOrDownload来加载AssetBundle，那么有两种情况需要考虑： 内存中加载的AssetBundle数量。在iOS平台上，通过该接口加载、同时存在于内存中的AssetBundle数量确实是有限的，接近300个，这是由于iOS上文件句柄数的限制导致。而该限制在Unity 5.0以后则被完善了，因为Unity 5引入了虚拟文件系统，所以不再有这个限制；在Android平台上，则没有这个限制，或者说数量限制值非常大，基本可以忽略。 本地Cache中缓存的AsseBundle数量。无论是iOS、Android还是PC版本，都没有500的数量限制，而是有一个硬盘占用大小限制。具体来说，在WebPlayer平台上，有50MB的缓存限制，而在其他平台上，则是4GB的缓存限制。所以只要硬盘占用大小不超过限定值即可。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/58ec4807da71c21b3b1ac91c 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q3：我阅读了UWA的你应该知道的AssetBundle管理机制一文，想对其中“每次加载都涉及到解压操作”的理解进行确认：对于new WWW实际是解压到WebStream。而如果是用的LoadFromCacheOrDownload，那么资源是在磁盘，所以在调用www.assetbundle时才做解压。那么有个问题，如果使用直接获取AssetBundle的那些API，解压过程是怎样的呢？CreateFromFile是在调用assetbundle.load的时候从磁盘解压，CreateFromMemory是直接解压到WebStream？ 另外，对于WebStream来说，同一个WWW对象多次调用www.assetbundle方法时，得到了栈上的多个变量，但是这些变量都指向同一个WebStream中的对象吗？ 对于第一个问题，AssetBundle的解压均发生在加载API的调用处，而不发生在www.assetbundle时，即无论是New WWW、LoadFromCacheOrDownload、LoadFromFile还是LoadFromMemory，其AssetBundle的解压均在上述API调用处。在Unity 5.3版本之前，Create/LoadFromMemory是直接解压到WebStream中，而在5.3后，则已经不存在WebStream这一说法了。具体可以查…

技术分享连载（五十九）
type: item
date: 2017-04-11T05:16:00+03:00
description: 本期我们聚集了这些话题：AssetBundle粒度规划、Android上的多线程渲染、Instantiate实例化堆内存占用、动画模块中函数的CPU占用... 我们将从日常技术交流中精选若干个开发相关的问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：793972859 UWA 问答社区：answer.uwa4d.com 资源管理 Q1：关于AssetBundle（下称“AB”）拆分粒度问题。在我的项目中，我是基于逻辑以及最终的打包大小来分的，比如尽量不让压缩后的AB包超过1MB, 这是UWA之前的推荐，同时也是因为当前版本Android包的SerializedFile占用大小所考虑。经过这样的规划之后，我打包这块的代码基本是写死的， 包括手动把公共包拆成多个(公共包略大，不拆的话压缩后会有6、7MB)， 还有每个AB包的内容也是人为拆成多个。 这样虽然最后功能实现了，但个人依旧觉得不够自动化。每次新添加资源的时候， 都得走一遍这种手动流程。也研究了别人写的开源方案 ，全自动分析依赖关系，但问题是最后包打得实在太细了，不太符合科学(但还是推荐大家学习)。所以就想问下各位的公司项目是如何解决这个AB 粒度划分问题的？ 这是一个相当开放的问题，仁者见仁，智者见智。UWA目前无法总结出一个大一统的方式来建议如何进行打包，首先需要说明我们看到的两点情况： （1）没有最好的打包方式，只有最适合项目需求的打包方式； （2）无论是粗粒度打包还是细粒度打包，现在都有成功的项目在采用，这说明只要符合需求，两种打包方式都是很好的。 接下来，我们就粒度问题给出一些我们的看法： 1. AB粒度建议不宜过细，特别是一个资源一个AB。 粒度过细，一方面会导致加载IO次数过多，从而增大了硬件设备耗能和发热的压力；另一方面，在我们测试过的Unity 5.3 ~ 5.5 版本中，Android平台上在不Unload的情况下，每个AB的加载，其每个文件的SerializedFile内存占用均为512KB（远高于其他平台），所以当内存中贮存了大量AB时，其SerializedFile的内存占用将会非常巨大。同时，需要进一步说明的是，该问题已在Unity5.6中进行完善。 2. 在Unity 5.3版本之后，对于AB文件的文件大小其实不必再限定于1MB之内。 之前UWA有这一限定是出于两方面的考虑：一是New WWW在Unity 5.3之前是使用最为频繁的AB加载方式（虽然现在也是），在5.3版本之前，New WWW加载会形成一个比较大的WebStream，一般来说是压缩AB的4~5倍，会占用比较高的内存；另一方面，当AB较大（比如大于5MB）时，其加载开销会很大，由于是子线程中运行，所以真正反映到Profiler中时，大家会看到的一个“诡异”的CPU高开销——Graphics.PresentAndSync，具体原因可以看这里（ 扒一扒Profiler中这几个“占坑鬼” ）。所以，我们对此做了一些实验，发现将AB压在1MB以下是一个加载比较可以接受的情况。以上是我们之前为什么会提出1MB的主要原因。但Unity5.3之后，随着LZ4的引入，很多情况已经变化了，基于其Chunk的加载特点，AB加载很快，且内存占用要比之前小很多。所以LZ4的AB其实可以考虑更加粗粒度一些。 但是，这里仍然有以下三点注意： 1. 对于需要热更新的AB，也如问答中其他朋友的所言，要考虑实际情况控制AB的大小； 2. 即便是LZ4的AB，其加载方式不同，加载效率也可能完全不一致。以下是我们在UWA DAY 2017的分享，我们在两个不同的AB（LZ4格式）中都加载同一个资源，唯一不同的是一个AB包含10个Asset，而另一个AB包含30个资源，以下是三种不同方式从加载AB到AB.Load的耗时对比。可以看出，New WWW加载出现了明显的时间差异。因此，在Unity5.3之后，尽可能建议通过LoadFromFile(Async)来对AB进行加载。 3. 对于AB的打包，尽可能把逻辑上同时出现（一个Prefab中非Share的Asset）、小而细碎的资源（Shader、Material、粒子系统等）尽可能打包在一起，并通过LoadAll来进行加载，因为这样会带来更好的加载效率。下图为LoadAll和Load One By One的性能对比。在我们做过的实验中，LoadAll确实会带来更好的性能开销。 上述是我们建议研发团队在AB打包时的一些注意点，希望对大家的项目优化有所帮助。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/58e5bd96e042a5c92c3484ec…

技术分享连载（五十七）
type: item
date: 2017-03-29T08:51:00+03:00
description: 本期聚集话题：CPU和GPU的性能消耗、AssetBundle 兼容性、Animator精度优化、如何卸载引用资源... 精选5个性能优化问题，建议阅读时间15分钟，认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。 UWA QQ群：465082844 性能 Q1：在整体的性能消耗上，CPU和GPU各占一半合理吗？如果不是，各占多少为好？还是说需要根据机型来看？其次，我如何知道游戏在手机上的GPU消耗？Profiler是看不到的，有工具推荐吗？ 首先，CPU和GPU是并行的，也就是CPU在运算的时候GPU也在运算，一帧的结束时间是两者中比较晚结束的那个。因此，一般我们在考虑这个问题的时候，经常会说是CPU bound还是GPU bound，也就是GPU在等CPU还是CPU在等GPU。最理想的情况是两者都并行均衡，且都没有出现互相等待的情况。但在目前的大多数移动游戏中，都是CPU耗时为主要性能瓶颈。这也是为什么有多线程渲染的原因，多线程渲染就是利用CPU端的并行性，让CPU处理得更快，不拖后腿。 其次，对于GPU的压力分析，可以尝试用Intel GPA，Mali或者高通出的针对自家芯片的工具。 动画优化 Q2：UWA DAY 2017中提到“Animator优化可以把精度从8位减到3位”是什么意思？如何实现呢？ Unity的动画文件中每个关键帧数据的数值精度会达到小数点后6位以上（如下图一）。在Unity中可以通过将菜单“Edit->Project Settings->Editor”中的Asset Serialization选项设为"Force Text"获得动画文件的文本，然后通过文本处理将所有数据数值精度降低到小数点后3位（如下图二），这样可以使动画文件的大小降低。 图一 图二 以133s的动画文件为例，在不开启压缩时，其内存大小为31MB，使用Keyframe Reduction选项可以降为8MB，进一步经过降低精度后，可以降为3MB。 资源管理 Q3：我用DestroyImmediate 和 Resource.Unload 来进行卸载Prefab，在卸载前我获取Prefab下所有的材质，发现有些文件无法卸载，类似下图中的MangedStaticReferences()，怎么卸载这些资源呢？ 从图片上来看，这个是资源被逻辑代码缓存的问题。图中YangCheng纹理之所以无法卸载，是因为它被YangCheng材质所引用，而YangCheng材质又被UIAtlas脚本所引用，ManagedStaticReferences表示此资源最终是被逻辑脚本所引用，即可能某个脚本中的变量或者Container对其仍有索引。从该图来看，很可能是使用到该Texture的某个UI GameObeject没有被释放所致。建议研发团队可以检测一下具体使用YangCheng材质的索引情况，定位其被索引的原因。一般主要有两种可能，一是它自己本身被储存于脚本变量中，二是引用它的GameObject被储存于变量中。研发团队可先从以上两方面入手，对该资源进行检测和排查。 资源管理 Q4：我们项目做AssetBundle打包时，发现如果资源所依赖的C#Script的Public成员变量有变化时，用新代码加载旧的AssetBundle就会不兼容。有没有什么方法能判断这些Script在变化时是否需要重新打AssetBundle呢？目前我们使用.CS文件的MD5来判断是否需要重新打包，但其实这样应该有很多不必要的重复打包，对吗？ 该问题的本质原因是新代码的序列化信息变化所致。建议研发团队使用Unity 5的新的AssetBundle打包方式，默认情况下，Unity 5引擎会自动检测其脚本的序列化信息是否进行改变，从而自动进行增量打包。 资源管理 Q5：Unity的材质的宏是有材质用到时才会被编译吗？还是说不手动Skip都会编译？ 在Unity中shader variant也包含两种类型，一种是通过 shader_feature 定义，一种是通过 multi_compile 定义。而只有通过 shader_feature 定义的 variant 在发布时会根据其使用情况来进行剥离。具体可见Unity官方的文档：https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html 需要注意的是，放在Always Included Shaders中的Shader，其包含的所有 variant 都不会被剥离，因此对于Standard Shader这类包含了大量 shader_feature的Shader，不推荐将其放入。 今天的分享就到这里。也欢迎热爱进步的你加入UWA的QQ群（4650828…