UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - 技术分享
UWA DAY 2025 正式启动｜十年筑基，驱动游戏未来引擎
由侑虎科技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构建开放世界的技术点、不同版本新增了哪些功能、开放世界下pcg工作流展示、UE5.6的主要内容介绍以及未来的开发方向。 ➨ AI在游戏开发领域的颠覆式革新 麒麟子 Cocos引擎 技术总监 游戏引擎领域深耕15年，目前负责Cocos引擎的产品研发与开发者社区。社区 KOL、技术布道师、科技自媒体博主，接触了4000+研发公司，全网程序员粉丝15万+。当前阶段的核心任务，是研究AI技术如何转化为工作流和生产力，为产品研发带来极致的效率提升。 人工智能正在以前所未有的速度重塑游戏开发的每一个环节。从传统的手工编程到智能化工具辅助，从昂贵的资产制作到AI一键生成，从复杂的开发流程到30分钟构建游戏原型，游戏开发正经历着一场深刻的技术革命。本次分享将深入探讨AI技术在游戏开发领域的五大革新方向：开发工具、资产生成、技术栈、端侧AI、实时内容驱动。这不仅仅是一次技术分享，更是对游戏开发未来的深度思考。无论你是资深开发者、创业团队负责人，还是对游戏技术充满好奇的从业者，这次演讲都将为你提供一些思考和帮助。让我们一起探索AI如何重新定义游戏开发的边界，见证一个全新时代的到来。 ➨ UE-DS的长跑挑战 - 长生命周期大世界的性能治理探索之路 赵珂 腾讯天美J1工作室 高级工程师 十年游戏开发经验，2019年入职腾讯，先后在《ApexMobile》、《高能英雄》项目中长期专注UE4引擎网络同步和DS性能优化工作。目前在《元梦之星-山海寻灵》玩法中负责DS基建和战斗相关工作。 本次报告将介绍在使用UE4引擎开发一款长生命周期大世界游戏过程中面临的技术挑战和实践经验。在短单局射击游戏中，DS优化聚焦逻辑精简和单线程压榨，通过限制同步、关闭动画等常规手段提升承载；而《元梦之星-山海寻灵》的长生命周期大世界需直面复杂业务叠加与持久战斗体验的冲突，迫使优化思路发生本质转型。报告主要内容包括：常规DS的优化、长生命周期大世界的新挑战、长局优化的混合方案和实验探索。 ➨ 《归环》项目研发效率提升之路 贾伟昊 萨罗斯网络科技（深圳）有限公司 项目主程 毕业于清华大学软件学院，先后任职于网易、心光流美、字节等公司，积累了十余年游戏开发经验，喜欢思考和分享，目前担任《归环》项目主程序。 为了满足玩家对于内容和品质的需求，游戏项目的体量越来越大，动辄几百人的团队规模对于开发和协作效率的挑战也越来越大，如何让团队高效地生产出高品质的游戏内容，成为了项目成败的关键。本次报告将从研效基建、技术框架、工作流建设等方面和大家交流《归环》这款刚刚首曝的二次元产品在效能提升方面的一些思考和实践，也会和大家分享一些我们走过的弯路、踩过的坑，希望能够带给一同在游戏研发之路上探索的朋友们一些新的思路。 ➨ 大世界场景工业化：程序化生成x模块化资产x渲染优化工作流 何文雅 珠海西山居 资深技术美术 拥有16年游戏开发经验，现任职西山居技术美术经理。专注美术资产管线规范化，主导制定跨项目的美术标准与工具链体系，推动场景自动化生成、虚拟几何体、全局光照、画质分级等核心技术落地，致力于用引擎技术解放美术生产力，实现画质与性能的动态平衡。 在游戏工业化进程中，流程效率瓶颈与技术迭代需求已成为核心挑战。本次报告将分享《解限机》项目基于Unity引擎定制的大世界场景自动构建解决方案，揭秘超大规模场景高效开发的破局之道。主要内容包括：通过Houdini程序化生成实现自然生态系统自动化构建；采用模块化数据架构革新人文环境生产管线；并融合虚拟几何体等次世代渲染技术。在零成本改造美术流程的前提下，完成从场景生成到电影级表现的技术闭环。 ➨ 技术美术：AI在游戏研发中的应用探索- 搭建游戏开发AI智能体与AI生成美术资产工业化管线 丁彦清 资深技术美术 北京电影学院数字媒体艺术专业硕士，现就职于某游戏大厂，深耕游戏开发领域。曾参与《生死狙击2》、《矩阵·零日危机》等项目的研发工作，积累了丰富的实战经验。核心专长聚焦于：游戏渲染技术 - 致力于高品质视觉效果的实现与渲染管线优化；性能优化 - 对游戏运行效率有深入理解与实践，擅长解决性能瓶颈；AI技术应用探索 - 积极研究并实践生成式AI等前沿技术在游戏美术管线、内容创作及玩法创新中的应用潜力。 本次报告系统性拆解AI技术在游戏美术管线中的工业化实践方案，涵盖三大核心模块： AI智能体游戏开发实践：基于Dify构建的TA-Agent实现材质规范审查、性能风险预警、资产版本自动化管理；基于Dify构建的智能助手如何解决材质开发、性能优化等跨领域难题； 生成式工作流革新：通过ComfyUI实现3D模型→UI资产的一键转化（含IP Lora训练/ControlNet姿势控制）、PBR贴图智能生成（SDXL+Substance 3D Sampler联动）、立方体贴图批量化生产； 工业化管线集成：贴图生成工作流与Substance 3D Sampler的PBR管线对接方案，立方体贴图批量生成标准。 ➨ UE美术表现的非技术力思考 - 效果的合理偷懒 李季（老李头儿） 数字艺术家，TA 上海市美术家协会会员，上海市青年美术摄影家协会副秘书长，视觉暂留TA合伙人。第四届瑞云渲染大赛季军，第六届GGAC裸眼3D赛道季军，B站UP渲染封神榜TOP50，数字艺术作品参与2025大阪世博会Shining Hat，WESTBUND西岸艺术博览会，全国青年艺术邀请大展等国内外诸多艺术展览。服务对象包括米哈游、腾讯、网易、开天工作室等。 在虚幻引擎的美术创作中，“合理偷懒”并非降低品质，而是通过策略性取舍与美术思维重构技术实现路径，以最低技术成本撬动高效视觉表现。其核心逻辑在通过资源复用、流程优化与注意力引导，在保障表现力的前提下规避冗余劳动。本次报告将介绍资源复用策略以及视觉转移设计的两个方向，运用美学决策优先的策略以减少手动调优的负担。让技术成为创意的赋能者。 ➨ 稳定、高效、安全的出海之路 - 阿里云游戏出海解决方案 云骧 阿里云智能集团 高级解决方案架构师 10年云计算领域经验，15年数据库、大数据经验。现任阿里云解决方案架构师，熟悉医疗、教育和游戏行业，帮助多家大中型企业完成系统上云、出海架构规划。 在全球化浪潮不断加速的背景下，越来越多的游戏企业开始走向海外市场，但随之而来的技术挑战也愈加复杂。本次报告将从出海游戏的实际需求出发，结合案例，分享阿里云全球基建、系统架构等方面的优势和实践结果。帮助客户快速高效的开展海外业务，探讨阿里云提供的云产品和解决方案如何助力游戏企业实现稳定、高效、安全的出海之路，希望能为正在或计划出海的游戏客户提供有价值的参考与启发。 ➨ 移动端Unity游戏功耗调优的破局实践 周旋 侑虎科技 引擎开发工程师 随着移动端Unity游戏在画质精度与玩法复杂度上的持续突破，功耗问题已成为制约用户体验的核心瓶颈 - 过度发热不仅导致设备降频、性能波动，更会直接影响玩家留存与口碑传播。然而，当前行业对功耗的优化仍停留在经验驱动阶段：CPU主线程压力、子线程负载、GPU算力消耗、带宽占用等关键因素与发热之间的定量关联缺乏直观呈现，开发者往往陷入“盲目排查 - 试错优化 - 效果模糊” 的低效循环。 正是基于这一痛点，本次分享旨在为开发者提供一套可量化的功耗调优方法论。过去一年，UWA团队深耕移动端功耗优化领域，依托Perfetto性能分析工具与ODPM（On-Device Power Metering）功耗数据采集方案，构建了从底层机制到项目落地的全链路分析体系。 通过本次分享，我们期望帮助开发者建立“精准定位 - 科学优化 - 效果可测”的功耗调优闭环，切实解决项目发热难题，助力打造低耗高效、持久稳定的移动端游戏体验。 ➨ 从App到多平台小游戏 - 高效迁移的全链路优化策略 周旋 侑虎科技 引擎开发工程师 随着小游戏平台的流量红利与用户触达优势日益凸显，将成熟Unity App游戏迁移至多平台小游戏已成为行业重要的拓展方向。然而，这种跨平台转化往往面临引擎适配壁垒、性能瓶颈突出、资源约束严苛等系列挑战，导致多数团队在迁移过程中效率低下、效果不达预期。 过去一年，UWA团队深度参与数十个Unity游戏向微信、抖音等主流小游戏平台的迁移项目，在实战中系统性沉淀了覆盖迁移全流程的优化方法论。本次分享将聚焦迁移关键内容，包括：同步加载转异步加载的方案；URP性能优化；内存优化和iOS平台的渲染异常表现修正等。 我们期望通过这套经过验证的全链路策略，助力开发者规避迁移陷阱，实现从App到多平台小游戏的高效转化与体验升级。 ➨ 基于自定义格式对Unity场景的深度性能优化 李俊 欢乐互娱科技有限公司 引擎组组长 欢乐互娱引擎组长，曾任青果灵动黑光工作室技术负责人，字节跳动客户端主程序，技术专家。曾参与《黑暗之光》、《魔法王座》、《放置少女》、《RO仙境》等多款MMORPG和卡牌手游的研发。 重度MMO游戏中，大世界的场景加载效率、内存、渲染效率都是游戏性能的瓶颈。从提升流式块的加载速度出发，提出了无解码的自定义场景格式，大幅提升了场景流式加载速度，但是因为场景已经没有组件了，Unity原先支持的机制不再支持。在重新造轮子过程中，我们深度优化了场景内存、渲染提交等方面的性能，同时解决了被引入的新问题。本次报告将重点介绍的内容包括：无解码的自定义场景格式实现；Lightmap流式实现；自定义格式下地形渲染；基于Batchrendergroup的渲染优化等。 ➨ “AI拼UI”的探索历程 罗培羽 广州四三九九 主程序 就职于4399技术研发中心，负责前沿探索和技术支撑工作。著有《Unity3D网络游戏实战》、《百万在线：大型游戏服务端开发》等书籍。 “拼UI”一直是游戏前端开发的一个痛点，工作量大且繁琐，尽管已有诸如PSD2UGUI、FairyGUI等方案，但却也未能完全解决问题，很多时候是把程序的工作量转移到美术而已。4399公司的游戏迭代速度很快，“拼UI”是一个突出痛点，因此开展了使用图像识别方法辅助拼UI的相关研究。本次报告将叙述这一研究历程，包括最初使用传统的图像识别方法、后续分析PSD结构的迭代算法，以及使用大语言模型来辅助识别UI结构的探索。尽管“AI自动拼UI”离落地尚有距离，但这一课题是行业共同面对的痛点，通过分享其中的探索历程，以作启发。 ➨ Vibe Playing & Agentic & 共创游戏：新游戏体验与商业模型 蔡俊鸿（卡卡）潜在领域 CEO、CTO 游戏全栈开发者，游戏热爱者，极客 人工智能不仅正在改变游戏的开发方式，更正在重塑玩家体验与商业逻辑。从“千人一面”的任务到因人而异的剧情，从静态付费点到动态行为预测与实时个性化触达，AI正在成为驱动游戏留存与变现的新引擎，未来的游戏，不再只是研发人员为玩家开发，而是玩家与AI共创。本次分享将围绕从Generative AI驱动的内容生成，到Agentic设计理念下的动态剧情与交互体验；从AI Agents对玩家行为的实时响应，到Vibe Playing带来的沉浸式参与与内容共创，探讨如何用AI提升玩家留存与付费。如果你是研发、策划、或者是对AI充满热情的探索者，希望能为你打开一个Agentic Game Design的全新视角。 ➨ 探索基于模拟现实的应用开发 - 以Godot引擎为基础的辅助驾驶可视化案例 张骋 莲花跑车 高级技术专家，UWA学堂作者 10年游戏行业和8年汽车行业辅助驾驶开发经验，现就职于莲花跑车智驾部门，负责辅助驾驶人机交互开发工作，将设计优秀的技术解决方案视为长期事业。 模拟现实应用开发已经在生活各处逐渐出现，如智能家具、辅助驾驶等。目前辅助驾驶系统的高级可视化已成为了中国新能源汽车的标配。高级可视化功能需要精美的视觉效果和自由交互的能力，同时还需满足较为复杂的开发环境要求。本次报告将通过我们的开发实践，分享基于Godot引擎实现高级可视化的经验，相信程序化内容和受限环境的开发经验对Unity引擎用户及其它机器人交互系统的开发者也有很高的参考性。 ➨ 性能优化新基建：GPM 2.0，如何从 “被动修复” 到“主动赋能”，重塑游戏竞争力底层逻辑 张鑫 侑虎科技 CEO 在传统游戏性能管理模式中，卡顿、发热、降频等影响体验的问题，往往需依赖玩家反馈或舆情发酵后才被察觉。研发团队不仅要消耗巨大人力成本复现问题场景，更易因响应滞后错失最佳修复窗口，最终导致用户流失与口碑损耗。 UWA GPM 2.0 的推出，标志着游戏性能管理进入“新基建”时代 - 通过构建“主动赋能”的全新范式，实现从被动响应到主动预判的关键跨越。 本次分享将聚焦GPM 2.0的核心能力：解析其如何基于玩家真实行为数据构建分析体系，实现性能风险的及时识别；详解运行时卡顿帧分析功能，如何精准定位卡顿帧逻辑、代码耗时点与资源加载瓶颈；阐述崩溃检测分析模块如何实时捕获崩溃前的场景状态、堆栈信息，为根因定位提供完整依据。 通过GPM 2.0，研发团队可在用户感知抱怨前锁定问题核心，将性能管理转化为前置化的体验优化能力，从而显著降低用户流失率，以技术基建的升级重塑游戏竞争力的底层逻辑。 ➨ 搞性能，不一定是和美术做对抗 - 美术向TA在性能优化中的思路分享 Wek（韦克） 技术美术专家，《矩阵零日危机》TA负责人 北京电影学院毕业，10年游戏工作经验，曾参与项目《一梦江湖》（原名楚留香）、《燕云十六声》、《矩阵零日危机》。 不少项目在性能优化的时候都会遇到推进有阻力的问题，甚至有的项目会出现临近上线加班优化性能，但是最后还是不得已砍掉一些效果的情况。《矩阵零日危机》从立项到上线一直没有遇到类似问题，可以实现较好的性能和美术效果的平衡。本次报告将分享美术向TA在性能优化中的思路和方法。 ➨ Unity引擎资源管理经验 - 如何使用YooAsset进行高效的资源管理 何冠峰 途游游戏 技术专家 YooAsset资源系统作者，长期专注于游戏开发领域，热爱技术研究和开源社区建设。技术特长包括游戏资源管理，游戏框架设计与性能优化。 在使用Unity引擎开发移动端游戏时，资源管理至关重要。合理的资源管理可以优化游戏的运行效率，减少加载时间，提高用户留存率。本次报告将深入讲解Unity资源管理，从资产管理到性能优化，全面讲解YooAsset的高效能应用。重点内容涵盖：资源管理与打包策略、自动化脚本配置、加载卡顿优化与调试工具使用，以及常见问题的解决方案。 ➨ 《仙遇》MMO手游工具链设计的思考与实践 李博皇 海南元游信息技术有限公司 客户端主程 拥有多年游戏研发与项目上线经验，专注技术创新与突破，持续推动协作效率与产品品质的提升。 制作一款大型MMO手游，工具链不仅是技术实现的手段，更是保障研发效率与产品品质的核心支撑。本次报告将围绕《仙遇》项目从立项、研发、上线到运营全过程，探讨所采用的工具链设计理念及其背后的原因，聚焦于为什么要有这些工具及其设计初衷（Why），以及它们如何提升团队协作效率和优化产品性能。通过回顾工具链的设计与迭代，分享实战经验，期待为同行提供参考。 ➨ 如何用物理驱动游戏角色 许晨光 （Shadow） Nubrain Game Studio 工程师 独立游戏《无极道人》开发者。 在各种游戏和3A大作中，为玩家提供更丰富可信的角色动画一直是业界追求的方向之一。基于物理的角色运动系统是一种利用物理引擎实时模拟角色运动和动画的游戏开发技术。与传统的预设动画驱动的角色控制不同，它通过力学计算各种运动中的力和碰撞反馈等效果来提供更丰富的视觉表现，以及实时与周围环境物体交互的能力。本次报告将介绍如何实现一个基础的由物理驱动的角色运动系统，以及对于传统物理引擎的算法在驱动物理角色时遇到的一些问题的改进思路和尝试。 ➨ Unity移动游戏工业级性能优化指南 3.0 余含章 侑虎科技 技术支持工程师 在过去一年中，UWA团队持续深耕于各项目性能优化一线，聚焦游戏研发过程中的各类疑难问题，不断沉淀实战经验并致力于向行业开发者分享。本次分享的《Unity移动游戏工业级性能优化指南 3.0》，在内容上实现了多维度的升级与深化： 其一，针对数年前完成的内存与加载测试进行重置与细化，在Unity 2022版本普及率持续提升的当下，重新验证既有结论的适配性与可靠性； 其二，系统梳理了新版Unity的高频问题，涵盖新接口评测、内存“黑洞” 定位等核心痛点，提供针对性分析； 其三，专项剖析iOS包相较于Android包更易出现的内存紧张、闪退等差异化问题，并配套输出经过实践验证的优化策略与落地经验。 我们期望通过本次分享，助力开发者更精准地解读数据背后的逻辑，共同探索性能优化的深层价值。 ➨ Tripo 3D大模型如何赋能全球游戏行业 宋亚宸 VAST 创始人、CEO VAST创始⼈兼⾸席执⾏官，本科毕业于约翰霍普⾦斯⼤学，曾在商汤科技落地了多个从零到⼀的⼈⼯智能项⽬，实现AIGC技术在动画及游戏行业的商业化落地，也曾参与创⽴通用大模型独⻆兽MiniMax。 为了适应全球用户对于3D用户体验升级、内容表达创新和新质生产力提升的持续追求，Tripo Studio重新定义了AI驱动的3D内容创作流程。本次报告将围绕VAST正式发布全球首个AI驱动的一站式3D工作台Tripo Studio展开探讨，例如：如何让每个创意都能从模糊构想走向完整成果，让3D创作不再止步于模型生成，而是获得完整、可用、有价值的可交互3D内容。 我们期待能为相关领域从业者提供“基础模型 + 生态插件 + 原生工作台”的端到端产品体系，从而构建覆盖从专业级（PGC 生产者）、达人级（PUGC 创作者）到大众级（UGC 用户）的创作者，进而推动全球3D内容创作领域新发展。 ➨ 3D MMORPG手游征服2GB设备之历程 张益宁 欢乐互娱科技有限公司 技术专家 《仙境传说：爱如初见》性能优化负责人，擅长技术架构，性能优化。喜欢为玩家带来极致游戏体验的同时，探索技术的极限。曾就职于腾讯，字节，吉比特，趣加。 3DMMO游戏在全球受众广泛，但因其复杂的业务需求，在2GB/3GB手机上内存面临极大的挑战，而这一部分用户，对于发行买量，游戏生态的构建，又是不可忽略的群体，基本每一个项目都会花费大量的精力在内存优化上。本次报告主要介绍一种系统的解决3DMMO游戏内存问题的思路，让3DMMO游戏畅通无阻的覆盖全球手机设备。 ➨ 《心动小镇》内存优化经验谈 刘贞明 心动网络 小镇技术组负责人 2009年进入游戏行业，先后供职于2K Games、CCP Games、Red Accent以及心动网络，有Console与Mobile平台的开发经验，并参与了心动多款自研项目的性能优化工作。 本次报告主要介绍《心动小镇》项目在内存优化过程中遇到的挑战和经验。具体包括： 项目的设计特点和在内存方面的挑战，例如：大世界、无缝集成家园、家园承载上限、潮流季等动态活动内容。 项目内存问题的分析与定位的流程、工具、方法和经验。 项目线上数据收集方法：自研工具及线上数据分析的方法及帮助。 我们为《心动小镇》实施的内存方面的优化方案，例如：针对资产系统（AssetBundle）的分析与方案、ECS化（去GameObject化：地形、草、树、岩石、房屋、HLOD、BRG等、Streaming系统、物理方案、Significance Manager、Jobs Animator、Shader的优化、配置数据库化、资产方面的优化（Mesh精度压缩、骨骼层级优化、贴图通道合并等），以及引擎相关的优化方案。 ➨ 动态大规模场景破碎解决方案，及有重量感的角色物理场景交互 唐翎（flashyiyi） 幽灵猫科技 独立游戏开发者 6年游戏行业经验，5年Unreal图形引擎/技术美术，知乎作者，知乎5W关注。曾在《影之刃零》和网易《归唐》项目任职；目前在制作个人独立游戏《猫咪漂移》。 本次报告将会介绍一种少量修改引擎代码，就可以让Unreal的Chaos物理引擎支持大规模的破碎且确保卡顿现象不出现的方案，以及一种可以避免角色和模拟物体碰撞偶然产生的“超高速弹飞”，“挤压抽搐”现象的方法。这两个方案在技术层面上可以基本解决开发者在游戏中加入实时物理模拟的顾虑。 十周年特别福利｜致敬每一位支持者 为感谢广大开发者一路以来的信任与陪伴，UWA在十周年之际特别推出【UWA用户专属免费票】！数量有限，先到先得。点击即可报名！ 活动信息 主办方：侑虎科技 时 间：2025年8月1日~8月2日（周五、周六） 地 点：上海市静安区广中西路333号 上海宝华万豪酒店 扫描上方图片二维码报名 感谢每一位提前锁票的你，是你们的热情与期待，让这个八月注定不凡。 让我们在代码的碰撞与灵感的激荡中，一起书写游戏产业的下一个黄金十年！ 了解更多大会详情，敬请关注官方平台后续发布。UWA DAY 2025，期待与你现场相见！ 往届精彩盘点 UWA DAY 2024｜创新潜藏无限可能 UWA DAY 2022｜躬身入局 践行游戏研发工业化 UWA DAY 2021｜助力游戏研发迈入工业化时代 UWA DAY 2020｜品往鉴来 质存高远 UWA DAY 2019｜以数之名，赋能游戏精品化 UWA DAY 2018｜快、精准、有温度 UWA DAY 2017｜没有横空出世，只有厚积薄发 关于UWA UWA是一家创业十年的高新技术企业，作为游戏行业的深耕者，UWA始终专注于为使用Unity、Unreal引擎的开发者提供丰富的优化产品，帮助开发者高效解决开发问题、定位性能瓶颈、提供解决方案，已支持超过一万款游戏项目。还打造了技术博客、问答、开源库、学堂等社区产品，为开发者提供便利和高效的支持。线上培训和线下教育的新业务， 满足行业对人才培育的需求。
关于Unity UI的动静图集分离，你需要了解这些！
本期我们聚集了这些话题：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）题主项目用的是Animation老版本动画系统； （2）对含有Animation组件的GameObject进行了大量频繁的Active或者Instantiate操作，一般这种情况比较常见于特效、UI HUD、角色/怪物等。 对此，研发团队可以通过上述两点查看是否如此。 该问答由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a953c61d35eb22c10a0a29d UI 管理 Q4：在UI优化中，是每张图集的内存占用对效能影响显著，还是图集数量（draw call）显著？比如8 张 1024 图集 和 2 张 2048 图集哪个更优？ 其实没有统一的标准说8 张 1024 图集 和 2 张 2048 图集那个会哪个更优，比如如果4张1024的贴图会一直在同一个UI中出现，同时加载同时渲染，那通常合并成一张2048的图集会更合理，而如果这4张1024的贴图在只在很少情况下才会同时出现1-2张，那合并成2048的贴图就是内存浪费。 这种极端情况的处理方式相信题主可以想到，所以这里是一个根据具体需求的选择，而没有哪个更好，具体的选择标准还要看项目是内存更加吃紧还是UI的DrawCall更加吃紧。 个人建议是，对于可能会常驻内存的，通用的那些资源，可以给予更高的图集大小的限定，比如允许最大2048甚至4096一张；而对于单个游戏功能内部的独有图集，我们是建议UI控制在1024以内，如果使用量到了3张1024的级别，才允许使用2048的贴图尺寸。毕竟如果分配合理，多一张贴图理论上可以做到只多1个DrawCall，而2张1024如果要用2048的贴图，空白的地方会比较多，或者不合理的合并，会导致内存占用比较浪费。 感谢UWA问答社区 @贾伟昊 提供了回答，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a947cf00b827e2c0bfdd014 渲染 Q5：Unity 5.5.2f1版本的项目中有少量模型在使用Cull Back的Shader时，渲染异常。我新建Unlit Shader，添加Cull Back的tag；用该Shader渲染角色的时候，发现如下图问题： 将Cull Back改为Cull Off 、Cull Front时，效果正常。 所以，我怀疑该模型的正反面反了；但是据我们美术说，3dmax中网格的正反面是由法线方向决定的,而法线方向是正确的，所以不是模型资源的问题。 所以修改Shader，将法线作为片段着色器的输出后，得到下图结果： 看上面这图，法线好像也没啥问题，那问题原因在哪呢？相关的例子我已经提交至UWA问答官网。 UWA：三角形面片的front和back不是由法线决定的，是由三角形的三个顶点投影到屏幕上的顺序决定。默认情况下gles是以逆时针方向的面为front，顺时针为back。虽然上面法线方向是对的，但是它跟face culling没有关系。从上面结果看应该是美术输出时候三角形面片顶点顺序弄反了，让他们改过来应该就行了。 关于face culling可以参考这两个函数： https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glCullFace.xml https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glFrontFace.xml 其实，face culling和法线反了是两种相像。 face culling的，你在那个Shader里加一句Cull Off，如果显示正常如上图，就说明面反了。 法线反了，选中模型时在右下角的预览(或直接拖到场景里打上光)，你会看到黑乎乎的，为什么呢。dot(lightdir,normal)，因为法线反了，这个值基本为0，diffuse 乘上这个值也会为0。 感谢UWA问答社区 @Kent 提供了回答 欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a97763fd35eb22c10a0a2c3 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问答也许都只是冰山一角，像这样实用的知识点在UWA问答平台（answer.uwa4d.com）上还有一打！UWA欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。
本期聚集话题：优化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）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期聚集话题：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老版本动画的AddClip功能。这种需求需要替换AnimatorController，研发团队可以在动态加载AnimationClip的同时，动态加载相应的Animator Controller，然后进行替换即可。 以上方法研发团队可根据自身实际情况而定。 动画 Q4：为什么Transform.设置Parent会触发Animator的初始化吗？Parent是等于null的。 把 Parent 设为null，相当于把这个 GameObject 变为根节点。如果在设置之前这个 GameObject 本身是激活状态，但其的父节点是未激活状态，那么设置之后，相当于把这个GameObject 激活。而激活GameObject 时就会触发 Animator.Initialize 等操作了。 资源管理 Q5：美术做粒子的时候，粒子与粒子之间共用资源的情况很多，例如某几个粒子共用一个Material，某几个粒子共用一个贴图等，应该如何组织AssetBundle？要是对应到最细的那个程度，凡是共用过的资源都单独打一个AssetBundle，好像又会很琐碎，假如不那么做，粒子与粒子之间的AssetBundle又会有冗余。这方面有什么好的建议？ AssetBundle打包没有标准的方式，单就粒子系统而言，因为其个体本身比较小，并且在项目中经常大量出现，所以并不建议将粒子系统逐个打包，而是建议根据其出现频率进行打包，比如将同一段时间、同一出现场景等的粒子系统打包在一起。同时，由于粒子系统的Shader基本上都是Unity内置Shader，因此，尽可能将Shader进行依赖打包。我们在UWA Day 2017上对于这种情况进行了详细说明，其Shader在中低端移动设备上的加载开销较高，需要研发团队特别关注。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：465082844（仅限技术交流）
本期我们聚集了这些话题：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在堆内存不够用时，会先触发GC释放5MB内存，这样即便9MB堆内存完全不能释放，那么总共内存占用为19MB，也小于当前的20MB峰值。但上述仅是数字上的表意性描述，Mono本身堆内存分配和释放是更为复杂的逻辑，一切仍需从实际情况出发。但需要注意的是，一次性分配9MB堆内存，确实是需要尽可能从设计上进行规避的。 动画模块 Q5：我在优化动画精度时发现针对Generic效果明显，而Humanoid变化不大，第一组图是Generic优化前后对比，第二组图是Humanoid，优化前后对比，这是为什么呢？ Generic优化前后对比 Humanoid优化前后对比 精度优化降内存（并非通过减少位数降低文本体积降内存），其实质是将曲线上过于接近0的数值（例如有效数字出现在小数点6位以后）直接归零，使部分曲线变为constant曲线来降低内存消耗。在Generic中，大量曲线存在这样的数值，因而降低精度后，constant曲线增加，内存降低。但在Humanoid中，动画信息被转化到Muscle空间后，muscle曲线上的数值很少约等于零，很难因为精度降低变为constant曲线，因此内存占用受精度降低的影响不大。但归一化的Muscle空间本身就对动画信息进行了精简，自身内存占用相比Generic已经降低了不少，如果需要继续降低，可以尝试提高压缩选项下的Error值。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期聚集的话题：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 耗时增加，但是相比于直接增加mipmap level（也就是设置-0.5的偏移），要达到相同的效果，Anisotropic Filtering的时间耗时还是相对更低的。这个参数影响的是GPU端的时间开销，我们没有单独统计过，研发团队可以尝试提交一个版本到UWA网站上（www.uwa4d.com），我们从整体效率进行分析检测。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/590198b09db5d16c66166148 如您对该问题仍有疑问，可以转至社区进行进一步交流。 资源管理 Q4：我们使用的是Resources.Load和LoadAsync的方式加载资源，这个与AssetBundle的方式比较，能大概帮解释一下优劣么？ 目前大量项目都在使用AssetBundle进行加载。相较于Resources加载，其好处有如下几个： （1）游戏启动更快，Resources文件夹下文件数量越多，游戏启动越慢，而AssetBundle的使用可以极大减少Resources文件夹下的文件数量； （2）更方便于资源的加载和热更新，AssetBundle可以让资源组织更为灵活，根据项目的不同情况，可以更为方便地对部分模块进行预加载或热更新。 资源管理 Q5：在Unity工程里启动游戏时，会有大量的Warning（类似定义了没有使用的变量这样的Warning）请问这个对真机的性能是否有影响，是否有必要修改掉这些Warning？ 如果在真机运行时，依然会存在这些Warning，那么对于性能来说是有影响，建议尽可能将其去掉。而像问题中提到的"类似定义了没有使用的变量这样的Warning"，这种属于编译时候的Warnning，是不影响运行时性能的。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期我们聚集了这些话题：优化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是否合理？这个分配数值可以接受吗？是否存在泄露？如果存在泄露，有没有具体到每个函数的分配详情？ 研发团队可以在测试报告中查看 Mono堆内存分析报告，这里有我们对于Mono堆内存的详细分析，包括 堆内存具体分配 和 堆内存泄露分析 两大功能，如下图所示。 就研发团队目前的数据报告来看，其堆内存分配其实是很小的，之所以有目前的堆内存调用，推测是手动调用GC的频率较高所致，研发团队可以就此再进行进一步的检测。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期我们聚集了这些话题：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这一说法了。具体可以查看官方文档：https://docs.unity3d.com/Manual/AssetBundleCompression.html 对于第二个问题，同一个WWW对象，多次调用www.assetbundle时并不出现WebStream的Clone操作，即这些变量均指向同一WebStream对象。 动画模块 Q4：我们在内存优化时发现一个问题，编辑器版本 Unity 5.3.4p6，使用UGUI，场景A中一个Text控件使用自定义字体资源，然后把该控件Text属性勾选为空（disable），再Load一个空场景，看场景A卸载后在内存中的残留，发现有一份引用是 ManagedStaticRefrences（）的 Font 内存。如果不是把Text属性disable，则场景A卸载后内存里不会再残留被引用的Font内存，请问可能是什么原因造成的呢？相关例子已经提交给UWA。 UWA对于该例子进行了检测，的确能够在 Editor 复现。查了下 UGUI 代码，能对 Font 产生引用的，主要是这个函数 FontUpdateTracker.TrackText(Text)，其中会把 t.font 引用起来；而对应的解引用的函数为 FontUpdateTracker.UntrackText。因此，如果出现了两者的调用不匹配，就有可能造成 font 的 ManagedStaticRefrences 引用。 进一步查看后，可以看到在定义了 UNITY_EDITOR 宏时，UI 元素会增加一个名为 OnValidate 的函数，Text 组件则在其中进行了 TrackText 的操作。 而最关键的是，该函数在 Text 组件以“未激活”的状态被实例化时同样会被触发，同时，如果这样的 Text 组件在后续没有被激活过就被销毁，其 OnDestroy 和 OnDisable 函数是不会被调用的，参见文档中的这句话：OnDestroy will only be called on game objects that have previously been active. 而 OnDisable 中才会调用 Untrack 解引用，所以造成了不匹配，导致了 font 的 ManagedStaticRefrences。 但是，OnValidate 函数只在 Editor 上才有，真机上不会发生上面说到的不匹配的情况。所以建议研发团队先在真机上测试下是否还有这种情况，如果确实没有，那么就忽略该问题即可。 此问答来自于UWA 问答社区： https://answer.uwa4d.com/question/58e4e793e042a5c92c3484e1 如您对该问题仍有疑问，可以转至社区进行进一步交流。 图形渲染 Q5：我想了解如何使用顶点色Mask控制明暗关系，才能达到类似崩坏琪亚娜效果？ 贴一个之前Guilty Gear Xrd （http://qiankanglai.me/2015/10/09/ggx-part1）的例子，参考了 【翻译】西川善司「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密—前篇（1）(http://www.cnblogs.com/TracePlus/p/4205798.html) 中的做法： 研发团队可以在顶点色里刷入明暗信息，如下图： 原来的效果如下： 接下来把顶点色的明暗乘上去（或者用其他的运算，主要就是用来控制亮度） 注意左臂腋窝部分…阴影部分变大了。至于具体的控制方法，个人认为一般点乘居多，美术只要控制好顶点色输入的亮度就行。 感谢来自 UWA 问答社区的钱康来提供回答： https://answer.uwa4d.com/question/58e5ffe180ca640f2736fc94 如您对该问题仍有疑问，可以转至社区进行进一步交流。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（仅限技术交流）
本期我们聚集了这些话题：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/AssetBundle-%E7%B2%92%E5%BA%A6%E8%A7%84%E5%88%92 如您对该问题仍有疑问，可以转至社区进行进一步交流。 性能优化 Q2：我之前在参加UWA讲座时，听说移动端开启多线程，把后期效果移动到渲染线程会节省后期的消耗。我测试了一下，虽然主线程中后期显示的CPU占用降低了，但是却多了Gfx.WaitForPresent的时间，最后两者相加基本还是一样的。那开启多线程这个功能，对后期到底有没有帮助呢？ 我们在UWA Day上详细讨论了多线程渲染的开销。需要注意的是，开启多线程渲染一般情况下会极大降低主线程的渲染耗时，但并不会降低其本身的总体计算量。因为这并不是底层算法或硬件上的提升，而是将部分计算从主线程搬到了子线程。所以，开启多线程的好处在于为主线程带来了大量空间来执行其他耗时模块（如代码逻辑等）。但这并不意味着开启多线程渲染就“万事大吉”。如果渲染模块本身开销就很高，那么子线程一样会很耗时，更有可能出现主线程等待子线程的现象，也就是WaitForPresent开销较高的情况。所以，开启多线程是会降低主线程的渲染压力，但其帧率未必会大幅提升，还需研发团队自行在自己项目中进行尝试和比较。 Instantiate实例化 Q3：为什么Unity里实例化一个Prefab会产生那么多GC Allocated? 图中的Instantiate实例化操作应该是实例化一个较为复杂的UI界面，其中还通过Active/Deactive激活和关闭部分UI界面。Instantiate实例化会触发Object上挂载脚本的构造函数（..ctor操作）和Awake操作，而这些函数中的堆内存分配均被计算在Instantiate实例化操作中；同时，UI界面的Active和Deactive也会造成UI代码底层的一些相关OnEnable和OnDisable操作，同样会造成一定的堆内存分配。而上图中之所以堆内存分配量较高，是因为Instantiate和Active的调用次数较多，分别为93次和183次。因此，图中堆内存分配过高并不是实例化一个Prefab所致，是同一帧中实例化和Active了大量UI Prefab所致。建议研发团队对项目运行时的UI实例化频率进行进一步检测。 动画模块 Q4：请问动画模块中，Animators.ProcessAnimationsJob和Animators.WriteJob的CPU占用较高，请问这些与什么因素有关？ Animators.WriteJob受模型骨骼数目影响较大（受animation curves影响不明显），骨骼数目越多，该函数耗时越大。同时，开启Optimize GameObject选项能够降低该函数耗时。Animators.ProcessAnimationsJob 同样受骨骼数目影响较大，同时也受animation curves数目影响，二者数目越多，该函数耗时越大。 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站（answer.uwa4d.com）上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（非水群，仅限技术交流）
本期聚集话题：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群（465082844），也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。