UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - Unreal
做UE项目的你，一定经历过这些场景：QA测出卡顿 → 录屏反馈 → 程序复现半天，对不上。打开 Unreal Insights，却发现真机数据和Editor分析结果不一致： 跨线程（GameThread / RenderThread / RHIThread）互相影响，瓶颈像“黑盒”一样难以拆解，长周期卡顿、内存泄露问题，测得到却抓不住。最后问题不是解决不了，而是——定位成本太高，效率太低。 UE性能分析长期存在一个核心断层：开发侧分析工具（Insights）与日常QA测试数据之间，无法稳定对齐，这意味着：QA的数据，程序不能直接拿来主义、分析必须反复复现、性能优化高度依赖经验与人力，仍然是一件“专家工具 + 人肉分析”的事情。 随着 Unreal Engine 5.7的发布，UWA GOT Online UE版迎来全量升级。但这次，我们做的不是简单适配，我们想做的是：把UE性能优化，从“少数人能做”，变成“团队都能做”的标准能力。 原生级引擎适配 让数据第一次真正“对齐” 从“看数据”到“直接定位问题” 我们完成了UE 5.x全系列（含5.7）的原生适配，并打通了引擎底层数据链路。具体包括： 1. 函数级Timeline与Insights的100%对齐 函数名、调用层级、时间统计完全一致，这意味着：真机数据，可以直接用于定位问题，而不是“参考数据”，程序无需再在多个工具之间反复核对。 2. 引擎原生指标全量接入 新增5大类、数十条UE原生STAT指标，譬如覆盖了渲染流程中，从FDrawSceneCommand（RT）到RHIThreadExecute（RHI），每一层都有指标 + 函数堆栈，可以精确定位：到底卡在“哪一段渲染流程”。 另有，加载/GC/动画/物理/AI/UI，所有数据均来自UE原生采集通道，开发者看到的，就是引擎真实发生的。 物理模块 UI 模块 多线程核心指标（Game/Render/RHI）全面覆盖：支持多视角切换（总览/单帧/场景） 且支持独立线程分析、冰柱图 + 堆栈联动、万级节点自动过滤。可以直接定位到某一帧、某一线程、某一个函数。 性能优化第一次变成“团队能力” 这个版本中我们也支持了一系列对于日常调试需求来说非常友好的功能，譬如： 新增Direct Mode模式，支持游戏启动后，立即开始抓取性能数据。能够针对游戏启动后加载慢、内存增长快等特殊场景进行针对排查。 编译级开关可控，支持宏定义一键屏蔽 SDK，可在 Debug、Release 等不同编译环境中灵活控制 SDK 的启用与关闭，彻底避免了 SDK 对项目正常开发、编译与发布的影响。 集成流程简化，移除 Binaries 目录，降低了项目版本管理与团队协作的成本。 这次升级里，最具行业意义的一点，QA可以参与性能定位了： 过去：QA → 发现问题 → 程序分析 → 来回拉扯 现在：QA → 直接提供可定位数据 → 程序直接修 带来的本质变化是：性能优化，从“程序能力”，变成“团队协作能力”，并且覆盖研发全周期的性能管控，从SDK接入、功能测试、性能回归、长周期监控、一套工具全部覆盖，支持 Android / iOS；不只是“跑得快”，也关注“玩家体验”。 从2015年至今，UWA始终专注于性能优化领域。但这一次，我们更在意的是另一件事：能不能把“复杂能力”，变成“标准流程”，如果你正在做UE项目，并且遇到这些问题： 性能问题定位效率低 QA与程序反复沟通 长周期问题难复现 那这次Unreal版的GOT Online，就是为你准备的。我们做的，不只是工具升级，而是让性能优化这件事，第一次可以被“团队稳定复用”。 关于UWA UWA是一家创业十年的高新技术企业，作为游戏行业的深耕者，UWA始终专注于为使用Unity、Unreal引擎的开发者提供丰富的优化产品，帮助开发者高效解决开发问题、定位性能瓶颈、提供解决方案，已支持超过一万款游戏项目。
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引擎的开发者提供丰富的优化产品，帮助开发者高效解决开发问题、定位性能瓶颈、提供解决方案，已支持超过一万款游戏项目。还打造了技术博客、问答、开源库、学堂等社区产品，为开发者提供便利和高效的支持。线上培训和线下教育的新业务， 满足行业对人才培育的需求。
1）PlayerSettings.WebGL.emscriptenArgs设置无效的问题 2）java.lang.NoSuchMethodError的不明崩溃问题 3）UE电影摄像机旋转问题 4）Android设备游戏切后台后唤起，有概率变卡且黑屏 这是第383篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：465082844 WebGL Q：游戏里用了C++的第三方库集成到xLua里面，端版是用CMake构建，可以配置宏、Include路径等，很方便。 我现在用Unity 2021.3发布的WebGL版本，xLua是把所有Lua代码放在了“工程目录/WebGLPlugins”下面，在引擎里去#include这里的C代码，也没问题。 但是自己的C/C++代码比较多，也不能全部扔在同一个目录下，如果加了目录，就有跨目录Include的问题（主要是lua.h，lauxlib.h）。从实际表现来看，include .c或.cpp时，用到的.h文件如果是在同目录就没问题，如果跨目录了就会找不到。 我用PlayerSettings.WebGL.emscriptenArgs = "-Imy_file_folder_path"；这样设置搜索路径，但是没用；然后定义宏-Dxx也没用，不知道为什么。（参数中没有自己定义的路径和宏，都是Unity自己的，虽然ProjectSettings.asset已经生效了。） 请问有解决方案吗？ A：可以试试： PlayerSettings.SetAdditionalIl2CppArgs("--compiler-flags=-Imy_file_folder_path"); 感谢littlesome@UWA问答社区提供了回答，欢迎大家转至社区交流分享： https://answer.uwa4d.com/question/660d2b385c7f5d2c5805d38e Crash Q：最近被Android的一个崩溃搞得毫无头绪。烦请各位大佬帮忙指导分析一下。 这里是从Bugly截取的最后一段崩溃日志，Unity线程运行良好。然后一个不知名线程突然就报了一个java.lang.NoSuchMethodError的崩溃，更奇怪的找不到函数名name='Thread-37' ，来源文件也是Unknown Source。 19404-18 15:18:27.898 21248 21470 I Unity : CreateScene sceneInst complete 2 19504-18 15:18:27.911 21248 21470 I Unity : Lod level: 1 19604-18 15:18:28.264 21248 22705 W Unity : ! parseType; T is not known! 197--------- beginning of crash 19804-18 15:18:28.282 21248 22705 E AndroidRuntime: FATAL EXCEPTION: Thread-37 19904-18 15:18:28.282 21248 22705 E AndroidRuntime: Process: com.readygo.barrel.gp, PID: 21248 20004-18 15:18:28.282 21248 22705 E AndroidRuntime: java.lang.NoSuchMethodError: no non-static method with name='Thread-37' signature='Thread-37' in class Ljava.lang.Object; 20104-18 15:18:28.282 21248 22705 E AndroidRuntime: at com.unity3d.player.ReflectionHelper.getMethodID(Unknown Source:162) 这个大概会是什么问题呢？全网搜遍没有类似的问题。 同时，此问题在GooglePlay后台报的崩溃错误如下： 初始是怀疑第三方库导致，但是和公司同项目组比较过。使用同样的第三方库的项目并没有出现类似崩溃。 所以请问有没有类似的问题经验或者思路启发？非常感谢。 欢迎有经验的朋友转至社区交流： https://answer.uwa4d.com/question/6620f1b05ce8a46b00fc4ce5 Unreal Q：电影摄像机在两个节点之间有时会转一圈，比如从A地标—B地标，一般来说相机是走直线距离的，但是我这边相机镜头会旋转一圈。 A：在Sequence的摄影机时间轴“Rotation”轨道上右键，勾选“四元内插”选项。 感谢Phil@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/662088bd5ce8a46b00fc4ce1 Android Q：Unity打出安卓，切后台马上唤起有概率变得很卡，等几秒后进入App，然后黑屏。 期间内存CPU都非常平稳，内存占用不到1G。黑屏后CPU就降为0了，内存无变化。变卡黑屏为随机，也有可能第一次上来切后台就变卡黑屏。 不知道哪位大佬遇到过这种情况，或有什么解决的建议。感谢感谢！ 异常发生时候的日志： A：optimized frame pacing 勾选去掉。 感谢沈杰@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6614f1e95c7f5d2c5805d397 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：465082844
1）Unity升级后打包AssetBundle变慢 ​2）打包使有些资源合成了一个资源data.unity3d，有些分开的原因 3）Unreal在移动设备中无法使用Stat命令获取到GPU Thread的耗时 4）Unity中如何看到相机视野范围内的剔除结果 这是第330篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：465082844 AssetBundle Q：最近升级到了2021，遇到个奇怪的问题。打AssetBundle包，前面的速度正常，打到场景的时候变的非常慢，每2个场景之间不知道为什么停了1分钟，几十个场景，加起来AssetBundle包不到20MB，打了1个半小时，如果我只打这些场景，速度就是正常的，完整打AssetBundle包到了场景这里就特别慢。 A：可以尝试用Scriptable Build Pipeline来打包，在输出目录可以看到json文件，用Perfetto可以打开这个文件看耗时信息。 https://docs.unity3d.com/Packages/com.unity.scriptablebuildpipeline@1.18/manual/BuildLogger.html 该问答由UWA提供，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6420fec76778221ae3074852 Build Q：为什么打出来的包有些是资源合成了一个资源data.unity3d，有些是分开的？ A1：可以看看是不是以下这个设置导致的： 感谢范世青@UWA问答社区提供了回答 A2：比较建议使用LZ4的压缩方式的，AUP上传纹理必须使用LZ4的压缩方式，TextureStreaming也依赖LZ4的压缩。 感谢Xuan@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/641c1a1b6778221ae3044550 Unreal Q：我在移动设备Android上，输入Stat Unit命令，结果显示： Frame：42.33ms Game：24.22ms Draw：42.22ms RHIT：25.00ms Mem：1.96GB Draws：496 Prims：545.33KB 为什么没有GPU的耗时显示呢？可能是什么原因？ 针对以上问题，有经验的朋友欢迎转至社区交流分享： https://answer.uwa4d.com/question/641d1ca66778221ae304da66 Rendering Q：Unity中如何看到相机视野范围内的物体？类似Unreal Engine的FreezenRendering功能，方便快速的定位视锥体剔除。 针对以上问题，有经验的朋友欢迎转至社区交流分享： https://answer.uwa4d.com/question/63b41cd03bd6691a9ddc485c 封面图来源于网络 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：465082844
GOT Online在去年就已经支持了Unreal引擎，它不仅灵活便捷，还提供了数据的深度分析，例如引擎各模块的耗时分布、资源的具体信息等高级分析功能。为进一步满足广大Unreal开发者的需求，近期我们增加了对Unreal 4.25版本的支持，同时支持“Lua性能分析”模式。目前该服务免费提供给Unreal开发者使用。 使用方法非常简单： 1）在UWA官网下载工具套件，参照文档说明集成SDK 2）在本地真机上进行测试 3）将测试所得数据一键上传到UWA官网 4）登录UWA官网在项目页面中查看对应的报告 目前GOT Online for Unreal提供三种模式：Overview（总体性能分析）、Assets（运行时资源检测）、Lua性能分析。关于之前已支持的Overview与Assets模式，详情可戳本链接。下文将对本次新增的Lua性能分析模式做介绍。当前仅4.25版本支持Lua模式，且仅支持SLua。后续我们会陆续支持其它Lua框架，同时也会陆续对4.20-4.24进行Lua模式的支持。 Lua性能检测目前分为三个部分：总体堆内存、CPU时间占用和堆内存具体分配。 1、总体堆内存 该页面记录了Lua的总内存走势以及Lua中几种重要对象的数量：Table、Function和Userdata。 2、CPU时间占用 在CPU时间占用页面，罗列了CPU累计耗时最高的10个入口函数。 点开这些函数，我们就可以查看这些函数的总体耗时堆栈、指定场景堆栈以及在任意一帧的具体耗时堆栈，帮助用户快速定位瓶颈函数。 3、堆内存具体分配 该页面便于研发团队定位Lua堆内存分配较多的函数，我们可以查看这些函数在任意一帧的具体分配堆栈，帮助研发团队优化Lua的堆内存分配，降低Lua GC的触发频率和触发时的开销。 切换查看方式，即通过“倒序调用分析”功能，我们就可以直观地定位到底哪一个Lua脚本中的哪一行代码在分配大量堆内存。这样，研发团队就能直接打开对应的Lua脚本，找到那一行和函数直接修改，优化变得如此简单。 注：Lua函数的命名格式为X@Y:Z，其中X是其函数名，在无法获取时，X会变为默认的unknown；Y是该函数定义的文件位置；Z则是该函数被定义的结束行号。需要注意的是，当Lua脚本以字节码运行时，该值将始终为0，因此建议在测试时尽可能使用Lua源码来运行，或者在编译字节码的时候加上-g参数以保留行号。 以上即为本次GOT Online for Unreal更新的功能。我们希望通过它能大幅度提升大家定位问题、发现问题的效率。该服务目前免费提供给开发者用，快跟着小编的脚本一起来撸羊毛！ 登录UWA网站，功能中选择GOT Online 点击立即体验 项目引擎选择Unreal 即可体验起啦~
1）URP关于多个摄相机的性能优化 ​2）Unity Addressables打包的时候如何设置BuildAssetBundleOptions.DisableWriteTypeTree 3）Unreal可以用于商业化游戏的热更新方案 4）UGUI SpriteAtlas在使用中回调实例化，AtlasRequested和Start的顺序颠倒 5）从AssetBundle中动态加载渲染管线，后期渲染异常问题 这是第224篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Rendering Q1：URP7.4.3，除开主相机外，还有一个子相机，用于将照到的模型渲到游戏主界面UI上。在Profiler中看到以下情况： 可以看到，在子相机中也进行了包括对LOD的计算，但子相机的CullingMask只开了一个名为RTModel的Layer，在这一层里只有一个3D对象。按说子相机CullScriptable这块开销不应该有才对。 目前怀疑可能的原因是URP会对每个Base Camera都进行这部分的计算，但如果用Overlay相机，又无法用原来的方式将相机的targetTexture渲到一张RawImage上了。 有人遇到过么？ A：题主的疑惑是：子相机的CullScriptable这块的开销不应该有那么大对吧（毕竟我只有一个物件）？ 这里有两个问题： 1.Culling到底做了啥，只有一个物件为啥要Culling那么久（难道只有一个物件也要做很多的准备工作）？ 2.你在Profiler里面看到的数据真的是真实数据吗？也就是说，子相机的Culling真的做了1.68ms吗？ 抛开这两个问题，也可以有更好的做法： 我们一共两个相机，主相机和UI相机，那么UI上显示的3D物件怎么办呢？ 我们有个虚拟相机，所谓相机，其实就是做一个VP矩阵，做一个RT，绘制可见的物件就可以了。那么使用Unity的SRP，随便在什么地方，设置一下VP矩阵，设置RT，接着绘制指定的物件（UI中所有的3D物件都会挂在这个物件下面），然后这个RT就可以随意使用了。 假如一个UI上有两个3D物件，尽量都放在一个RT上，如果不行，就放在两个或更多的RT上。只是会多几个绘制命令，几个RT（还不需要是全屏的），而且会多几个Swap RT的操作。由于我们项目没需求需要若干RT，所以假设一下，在这种需要若干RT的情况下，也可以用一个RT加多个Viewport来解决的。这个代码都是现成的，参考一下Cascade Shadow Map的做法，这样Swap RT也就省了。 综上所述，既然你都知道自己要绘制什么，就不要给Unity Culling的机会了。 感谢王烁@UWA问答社区提供了回答 Q2：数据是在Development Build中连真机看到的性能数据， 目前在使用类似于HLOD的方式来减少掉这个LOD的巨大开销。楼上说的“设置一下VP矩阵，设置RT”，请问这个VP矩阵的操作具体是什么？可否详解下或者有相关资料吗？ A：一切皆有可能！但不过这个不重要。然后你提的HLOD和LOD和上面的Culling没关系。VP矩阵就是view矩阵和projection矩阵。相机的作用就是提供这俩矩阵的。 如果你在管线里面设置了相应的矩阵，然后绘制指定的物件，就可以完全不用多一个相机，毕竟多一个相机就多一个Culling。 如果你对VP矩阵不熟悉，不清楚怎么实现，也简单。依然用一个额外相机，关上这个相机的Culling，然后在渲染pass中，不要绘制cullingresult.visibleobject，而直接用Graphics.DrawMesh或者CommandBuffer.DrawMesh绘制你要显示的那个3D Object的物件就好了。 感谢王烁@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f914de75d9aea5aa9719769 Addressable Q：原来的AssetBunlde打包的时候可以设置BuildAssetBundleOptions.DisableWriteTypeTree，使得包体小好多。今天项目尝试升级使用Addressables，请问该如何设置BuildAssetBundleOptions.DisableWriteTypeTree? A1：首先Addressable打Bundle包主要的脚本是BuildScriptPackedMode，在DoBuild函数内可以看到用了AddressableAssetsBundleBuildParameters这个类，这个类继承于BuildParameters，而BuildParameters有一个成员变量是public ContentBuildFlags ContentBuildFlags { get; set; }，这个ContentBuildFlags就是用于设置DisableWriteTypeTree的，BuildParameters是属于ScriptableBuildPipline的。 参考SBP的CompatibilityBuildPipline有以下操作： if ((options & BuildAssetBundleOptions.DisableWriteTypeTree) != 0) parameters.ContentBuildFlags |= ContentBuildFlags.DisableWriteTypeTree; IBundleBuildResults results; ReturnCode exitCode = ContentPipeline.BuildAssetBundles(parameters, content, out results); 我们在BuildScriptPackedMode.cs里也可以加上： var buildParams = new AddressableAssetsBundleBuildParameters( aaContext.Settings, aaContext.bundleToAssetGroup, buildTarget, buildTargetGroup, aaContext.Settings.buildSettings.bundleBuildPath); buildParams.ContentBuildFlags = UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree; 但是我在这儿测试了一下，并没有什么用，不知道是最底层没有支持还是我的测试用例有问题。建议用同样的方法，测试一下。 另外说一下，我看了一圈代码，在打包和压缩部分SBP并没有用到这个参数。而在处理场景依赖的地方，这个参数会被合到BuildSettings结构体提供给C++部分调用。所以这个参数应该最终传到C++层起作用。 感谢黄程@UWA问答社区提供了回答 A2：Addressable似乎没有给外部的接口直接来修改这个设置项，应该是需要自己写代码来修改打包方式了。需要自己写一个BuildMode，可以参考以下这个帖子中第五个问题的回答：https://answer.uwa4d.com/question/5e649911438f7d0db495c724#5e64a4e8438f7d0db495c725 核心的代码是要DoBuild中修改buildParams的设置项，buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree；如下图： 做了一下测试，发现是有效果的： 上面是默认的打包，修改后重新打包，变成下面的结果： 整体都变小了一点点，而且使用解开AssetBundle后，可以看到里面的内容变得很简洁。 感谢Xuan@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f8ec5959424416784ef2870 Unreal Q：Unreal方面，目前有什么可以用于商业化游戏的热更方案吗？ A1：因为我们公司是自己研发的一套框架，所以我也没有太在意是否有开源的Unreal热更新方案，印象中好像是没有的。 但基于Unity引擎的开源方案倒是蛮多，你们可以按照Unity的开源方案的思路实现一套，基本思路就是使用反射预先生成引擎的导出Lua接口。 如何利用反射呢？简单来说就是根据反射得到引擎接口的函数名，返回值类型、参数名和参数类型，由工具生成解析参数类型以及它的个数和顺序，返回正确结果的Lua导出函数int xxx(lua_State *L) 函数。对于类成员函数需要导出到Table里，根据C++类层级关系利用Metatable可以找到父类的Lua导出成员函数。 Unity开源方案如此，Unreal也可以如此，区别只是Unreal使用UClass UProperty这套，而Unity使用C#而已。你们可以尝试着实现一下。 感谢王远明@UWA问答社区提供了回答 A2：可以参考以下这个链接： https://github.com/Tencent/puerts 感谢lanyt@UWA问答社区提供了回答 A3：腾讯有两款Lua热更新的框架可供使用： sLuaUnreal 据说是《和平精英》手游采用的框架； UnLua 较sLua后推出的一个框架。 感谢Vest@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f8fa49d9424416784ef28b5 Script Q：请问UGUI SpriteAtlas使用中，AtlasRequested和Start的顺序颠倒，如下图： 测试工程可戳原问答获取，测试环境Unity 2019.4。 A：可以使用Timeline看到具体的执行时机，在Main.Update里面进行实例化的时候（我测试的时候把Main.Update里面的interval去掉了），Atlas的回调跑到第二帧了，而TestAtlasSprite的Awake、OnEnable和Start都在第一帧。在Main.Start里面实例化的时候，这些打印都在第一帧，因为Atlas的回调是在EarlyUpdate.SpriteAtlasManagerUpdate里面，而实例化出来的TestSpriteAtlas.Start是在FixedUpdate.ScriptRunDelayedFixedFrameRate下面的，所以就跑到了Atlas回调的后面。 这个图是在Update里面执行的情况。 这个是在Start里面执行的情况，可以看到都是在第一帧打印的。 这是在Main.Start里面执行实例化的Timeline的图，可以看到TestSpriteAtlas.Start是在Atlas的回调后面执行的。 这是在Main.Update里面执行实例化的Timeline。 EarlyUpdate，FixedUpdate这些回调的执行顺序可以参考： https://medium.com/@thebeardphantom/unity-2018-and-playerloop-5c46a12a677 感谢Xuan@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f743b739424416784ef24d6 Rendering Q：有人遇到动态切换管线，显示错误的问题吗？ 现有UBP项目需求在进入新的场景之后，切换到指定的渲染管线。在打包场景的时候将渲染管线一并打包到场景中，并通过以下代码来切换渲染管线。 GraphicsSettings.renderPipelineAsset = targetAsset; QualitySettings.renderPipeline = targetAsset; 但是通过AssetBundle加载出来的渲染流程：在后处理中，UberPost 缺少两个Keyword。 造成如下的图像。 在Project Setting -》 Quality里面手动设置成项目的hero_show管线则正常显示。 通过断点调试发现：在Render过程中，Keywords其实都是有赋值的。二者的流程均一致。 在PostProcessPass.cs文件中： void Render(CommandBuffer cmd, ref RenderingData renderingData) 但就是在Frame Profiler中抓帧显示没有Keywords。附上简单的项目测试： 默认是Windows平台。直接运行defaultScene即可。 如不是，按下面流程处理： 1. AssetBundle->build 2. 运行defaultScene. 链接：https://pan.baidu.com/s/1q3s6mAUwE723wTJ3VmS81g 提取码：8kwn A1：虽然没遇到过，但是能猜到原因。 先总结一下楼主的问题： Project Setting -》 Quality里面手动设置渲染管线，显示正常； 以AssetBundle的形式加载渲染管线，显示不正常，原因是Keyword丢失。 那么答案就很简单了。 因为这两种模式Unity对渲染管线这个资源的处理方式是不同的： 以第一种方式，Unity会认为渲染管线是个默认资源，将其全部打包进包体，并进行使用。 以第二种方式，Unity会将渲染管线，特别是渲染管线关联的Shader，判断其Keyword是否被使用，如果没使用，就优化掉了。 项目还没有看，我猜测楼主是在代码中开启的这两个Keyword，这种代码开启Keyword的方式，Unity检测不到，所以就丢掉了。 解决方法也简单，对付Keyword常用的方案，创建一个没用的材质球，使用相应的Shader，在材质球中开启对这些Keyword的使用打进AssetBundle，这样Unity就知道，这个Shader的这些Keyword是有用的，就不会Skip掉了（其实这个方法常被用于以防instance_on这个Keyword丢失）。 感谢王烁@UWA问答社区提供了回答 A2：想尝试楼上的方法，发现材质球并不能直接引用到UberPost这个Shader，因为这个Shader是放在Package目录下，于是参考了Packages目录下Shader打包这个帖子中的方法进行打包。使用编辑器的SVC采集方法采集了一下SVC，SVC里面的UberPost是有那两个Keyword的。将UberPost和这个SVC一起打包，拆包后可以看到ubqScene场景是引用了刚刚这个SVC中的Shader的，切场景后在Awake里面加载SVC并Warmup，然而也还是没有解决问题。最后我把题主的原始工程打了一个exe，运行发现并没有Keyword丢失的问题，渲染一切正常。另外打包成APK测试，在小米9上测试也是正常渲染的。 可能还是Unity编辑器的问题吧，类似于这个帖子： UnityEditor下加载AssetBundle，材质球Keywords正常，但是某些属性不存在 感谢Xuan@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f89a0aa9424416784ef2817 封面图来源于网络 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859（原群已满员）
本期我们聚集了这些话题：Linear Rendering的支持率、通过蓝图/C++在运行时修改MeshData粒子系统的Mesh、PSS增长定位、优化Lua逻辑代码产生的内存... 这是第135篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（原群已满员） 渲染 Q1：在此篇博客里，有提到Linear Space Color这个特性在安卓机上的支持率是61%，在苹果机上是71%。 不过这个数据是2016年的数据，已经不适用于现在了，我们希望能知道Linear Rendering这个特性在现在安卓机和苹果机上的支持率，当然，如果能区分地区（例如大中华区和东南亚各自的支持率）和更加细节（例如OpenGL ES 2和OpenGL ES3占有率、Vulkan支持率、iOS Metal的支持率等）就更好了。 另外，如果我们在Gamma颜色空间下，使用PBR流程制作手机游戏想要有更好的表现效果，有什么好的策略和方法吗？现在我们使用的是Metal-Roughness贴图，Shader是参考下面这篇博客，修改Standard的Shader代码写成的。 占有率这个东西，不同的统计渠道可以得出不同的统计结果，我这里没有具体的数据，只能提供个人的建议——2019年上市的3D游戏，除非特别小型，在国内市场，我个人认为是不用去考虑OpenGL ES 2.0的设备了。三四年前的千元机已经支持OpenGL ES 3.0了（比如红米Note2、小米2A），何必为了这点市场份额而额外增加那么多限制呢？（Alpha通道拆分、自己在Shader中做线性空间处理、Shader要注意贴图采样数量限制等等） 另外大致看了下题主贴的文章，其实是在Gamma的设置下自己在Shader中实现Linear Space的计算过程而已，这种方式有两个小问题： 1）增加GPU额外计算量，比基于硬件的方式消耗更大一点点； 2）最终的从线性空间转换到伽马空间的过程，注意最理想的是在最后一步来进行，如果有多个Pass，这里的计算过程在效果上可能有错误（单个Pass，没有后处理的情况下看上去是一致的）。当一个Pass输出的颜色会作为下一个Pass的输入时，也要将颜色转换回线性空间来计算才正确。 还有就是不仅仅albedo贴图，所有是颜色的贴图/通道都需要做这样的计算才是正确的。 使用链接中的方式可以实现线性空间的效果，比较老的游戏也通常是这样做的，但是我个人会倾向于直接使用Unity内置好的功能，性能上和便利性上都会更好一些。 另外，个人观点，基于PBR流程的话，在做好基准效果之后，程序能做的事情不多，毕竟都是物理计算的，后面的效果大都依赖于美术对于PBR的理解以及制作经验了。 感谢贾伟昊@UWA问答社区提供了回答 最近项目刚切到线性空间去，查了些资料，Linear Rendering需要支持OpenGL ES 3.0 ，Android版本参考4.3, 以下是一份Android版本参考数据，参考版本数据大致可以推出占比 ： https://blog.csdn.net/qq_29428215/article/details/80847211 iOS参考iOS 7的iPhone 5s。 经过我查看的资料和调研，我跟楼上观点一致，直接切线性空间。 感谢赵林@UWA问答社区提供了回答 该问答来自UWA问答社区，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5bd7df711ea0b505053cc4ee 逻辑代码 Q2：控制Lua逻辑代码产生的内存，如何回收才能避免内存峰值过大？ C#和Lua都可以在回收的时候被标记为null，从UWA报告中的曲线可以看出，C#的回收机制是一段时间自行回收，Lua却没有，可以理解在堆内存管理上是有区别的？如果避免这样的内存泄露问题，控制内存暴涨，有什么更好的回收方法？ 补充理解： 手动回收内存：Lua内存回收调用Collect，C#调用GC； 自动回收内存：C#申请的内存置空或Clear可以回收掉，而Lua描述中也是置空可以让其自动回收，但是下面的Lua变化曲线没有锯齿线的变化，这有点不明白了，是否我理解错了？ 自动回收的说法可能有点问题，Clear或者置空只能认为是解除对对象的引用，并没有回收对象的内存。 回收的时间点总是发生在GC时的，只是有些是手动调用的，有的是自动触发的。上面C#和Lua的曲线不同，应该只是GC触发的规则和时间点不同（C#的频率高，而且每次是全量的GC，一次性回收；Lua的规则会复杂些，而且还可能是分代的）。 然后也可能是C#层的堆内存分配的比较快，量比较大，所以看上去GC就比较频繁了。 调用Collect是可以触发回收的，通过lua_gc的第二个参数还能控制是否分步进行。不过从曲线上看，Lua部分的内存有泄漏的风险，才会出现峰值越来越高的现象，所以建议还是先尝试定位下泄漏问题。 该回答由UWA提供 避免内存峰值过大，如果只是交给自动GC很难满足。 一般来说，是结合手动触发GC，甚至设置合理的步进。在一些特定的场景，比如说战斗场景，在内存准许的情况下还可能采用的策略是停掉自动GC以防止自动GC引起卡顿，然后出来场景做一次手动全回收并且开启GC。 防止内存泄露同样是要特别注意的问题，比如说Local不小心处理成了Global无法释放，被table表强引用等情况导致无法释放，导致内存占用越来越大。 感谢赵林@UWA问答社区提供了回答 该回答来自UWA问答社区，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5bdbb80f73c493238df34080 虚幻&粒子系统 Q3：求助虚幻4大佬们的帮助： 1）有可能在蓝图中或者C++中对粒子系统的Mesh进行修改吗？ 2）或者说有可能把蓝图创建的Procedural Mesh赋值给粒子系统的Mesh吗？ Procedural Mesh的创建方法参考的是： http://orfeasel.com/creating-procedural-meshes 回答如下： 1）首先，题主要先确定需要Runtime修改的是单个ParticleSystemComponent实例的Mesh还是整个ParticleSystem（资源模板）的Mesh。两者都比较容易达成，引擎在渲染动态对象的时候，会每帧通过PrimitveSceneProxy的GetDynamicMeshElements收集实际的MeshBatch，ParticleSystem会根据Emitter的实际Instance类型，调用对应类型的GetDynamicData获取需要的数据。所以只需要给ParticleSystemComponent添加接口暴露给蓝图，用来设置新的StaticMesh，并且在接口实现中，传递给实际的FParticleEmitterInstance，FParticleEmitterInstance基类中新增SetMesh的接口，什么都不做，在继承类FParticleMeshEmitterInstance中，增加UStaticMesh*类型的成员变量，作为PerInstance的override用的Mesh数据，重载基类的SetMesh接口中把传入的Mesh复制给自己的Override用的Mesh，并在FParticleMeshEmitterInstance::GetDyanmicData接口最后NewEmitterData->Init的第三个参数改成 EmitterInstanceMeshOverride ? EmitterInstanceMeshOverride : MeshTypeData->Mesh。至于要改整个ParticleSystem模板的Mesh就更简单了，直接在SetMesh接口中换掉自己MeshTypeData->Mesh就行了。要做的完整需要对resourcesize，getmaterials以及计算bounds的相应接口做一些简单的调整。 2）用ProceduralMesh会比较麻烦，当然也不是不行，但这里有一些概念题主需要清楚：普通的StaticMesh是Assets，而实际的Component可以看成是使用某种Assets的实例。所以在Mesh Data中设置的其实是资源，在实际生成实例的时候，会利用资源的数据来生成对应的数据。而ProceduralMesh比较特殊，并不存在资源，只存在实例，如果想实现需求，需要把ProceduralMesh的各种stream（position，normal，tangent，vertexcolor等）转成Particle的FMeshParticleVertexFactory中的实际数据格式，参考FMeshParticleVertexFactory::FDataType和ProceduralMesh中对应的数据的结构关系。 感谢王祢@UWA问答社区提供回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5bcefd53ae74300ab0497bdb 内存 Q4：请教个问题，内存快速增长该如何确定是哪些导致的？我们的UWA测评报告中显示切场景的时候多了差不多两百兆。 UWA：这个是PSS内存增长，这块内存的进一步定位有两种方式：第一种是在UWA GOT Assets模式中，查看主流资源（纹理、网格、RenderTexture等）的增幅情况；第二种是传到UWA网站，进行线上深度测评，通过线上报告除主流资源外，可以进一步看到此处的提升是Unity自身增长，还是Gfx增长，如果是前者，则根据AssetBundle加载相关，如果是后者，则跟Texture、Mesh、ShaderLab相关，这样就可以比较清晰地定位了。 但是，需要注意的是，PSS的内存增幅要快于Unity引擎的实际内存增幅，即App中加载一个4MB的纹理，引擎增加的记录是4MB，而PSS可能增加6MB、8MB甚至更多，这个是由其OS和Driver来决定的。 该回答由UWA提供，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5be2b11773c493238df340d2 内存 Q5：Unity 5.6.6版本下，在PlayerSetting中改变了Logo和背景，如图一直在内存中 ，请问该如何处理呢？ UWA：恰好整过一样的问题，当时绕过的方法是在首场景中添加一个脚本，然后把splashimage挂上去，在这个脚本的 Start 中通过 Resources.UnloadAsset() 把 splashimage 卸载掉，后续应该就不会再出现了。题主也可以一试。 该回答由UWA提供，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5bdc279473c493238df34086 今天的分享就到这里。当然，生有涯而知无涯。在漫漫的开发周期中，您看到的这些问题也许都只是冰山一角，我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入，也许你的方法恰能解别人的燃眉之急；而他山之“石”，也能攻你之“玉”。 官网：www.uwa4d.com 官方技术博客：blog.uwa4d.com 官方问答社区：answer.uwa4d.com 官方技术QQ群：793972859（原群已满员）
随着游戏内容的日趋精品化和重度化，Unreal引擎逐渐走进国内开发商的视野并被使用，然而其高门槛的操作使用和项目本身的重度性也使得优化工作愈发复杂艰难。作为性能优化的服务商，UWA测评今天正式支持了Unreal 引擎开发的项目，帮助Unreal开发者高效定位并优化性能瓶颈，该服务目前免费提供给开发者使用。 在目前UWA性能测评报告中，不仅有宏观的总体性能概览和细致的引擎模块检测，对于一些重要性能函数，报告提供了详细的堆栈分配信息，结合报告中的实时屏幕截图，研发团队能更直观地针对性能瓶颈进行定位和修复，下面就跟随小编的脚步一睹庐山面目吧！ 总体性能走势概览、细分模块数据分析 在总体性能页面中，我们展示了测试项目在运行过程中的CPU耗时以及内存走势，研发人员能快速对项目的主要问题了然于胸。 总体性能趋势—CPU性能占用 而对于微观的细节问题定位，我们提供了各个引擎模块的重要耗时参数信息。如下图，在渲染模块中，我们提供了DrawCall、Triangle、半透明/不透明渲染、相机裁剪、可见性计算单元数量等耗时走势。 总体性能趋势—渲染模块性能 针对报告中每个引擎模块中的重要参数，我们以UWA Tips的形式进行了详细说明，用户可方便地从数据中找出游戏运行过程中不同模块各项指标的数据，如下图所示： 代码堆栈是定位性能瓶颈的鹰眼。在目前的性能报告中，我们支持了多线程耗时的详细查看：对于游戏逻辑具体耗时，研发团队可查看游戏线程的调用栈信息，对于渲染模块的具体耗时可查看渲染线程的调用栈信息。同时，我们将其他线程中耗时较高的Top 10函数列举在OtherThread中，方便用户查看。 点开上图中的某一函数，我们能查看该函数在运行过程中的具体代码堆栈信息，包括总耗时、自身耗时和调用次数等。通过总体堆栈和指定帧查看两个模式，结合项目的运行截图，可以对代码的运行效率了如指掌。 代码效率—代码堆栈 而对于内存和资源的使用，我们分别列出了CPU和GPU端的内存占用情况。 同时，报告中也列出了游戏运行中，不同类型资源的使用情况以及其所占用的内存。用户可以很方便地查看指定资源的内存占用走势，并对不规范的异常资源进行排查和优化。 具体资源信息 除了以上功能，UWA性能测评报告还提供硬件参数解析（PSS、温度、电量）、运行日志等数据检测，在此不多赘述，大家可参考这里的完整Unreal性能报告Demo，当然我们更欢迎大家来体验！ 如何使用UWA测评服务 用户注册登录UWA官网后，在项目标签下“新建项目”，填写项目名称并根据测试的平台下载对应的SDK。 根据提示集成SDK后编译生成测试包，在提交页面中提交，并提供对应的测试流程。提交后，即可坐等报告生成。 目前，UWA支持Unreal游戏/应用在iOS、Android和PC三大平台的性能测评，同时随着对Unreal引擎更深入的测试和研究，我们将探索更多性能参数的规律。在后续的研发中，我们会不断更新UWA的测评机制，力求为Unreal开发者提供更有针对性的分析和参考。
UWA从去年开始进入Unreal引擎的学习，并且从去年底开始发表了一系列关于Unreal引擎使用方面的技术文章。但是，今天的这篇文章与以往的功能介绍不太一样，我们想通过一个实际的案例来让你对Unreal引擎产生更加深入的了解。 由于吃鸡游戏的火爆以及精品MMO游戏对于场景的需求越来越大，所以，我们这两个月使用Unreal引擎对大地形的动态加载功能进行了研究。从中，我们希望可以搞清楚以下两点： Unreal引擎对于大场景动态加载的制作方法； Unreal引擎在当今移动设备上的性能表现。 为了让我们的地形展示看起来更加“漂亮”一点，我们放弃了自己手动制作大地形场景的想法（我们自己做的地形实在拿不出手），而是使用了之前在Unity引擎中使用过的大地形场景模型。除了最终的渲染效果，我们几乎是1:1地在Unreal引擎还原了该场景环境，其在真机上的运行效果如视频所示。 视频中左边是Unity引擎的渲染结果，右边是Unreal引擎的渲染结果。 本文将主要介绍我们通过Unreal引擎制作大地形的过程中遇到的问题，希望可以对正在或即将使用Unreal引擎开发大地形功能的研发团队有所帮助。本文主要包含三个部分： Unreal引擎的资源准备； Unreal引擎场景流式加载功能介绍； Unreal引擎在真机上的性能分析。 接下来，我们将分别介绍这四部分内容。 一、 Unreal引擎的资源准备 由于我们希望使用一个已有的案例资源来制作Unreal引擎的大地形加载，所以，我们首先需要解决的，就是如何将Unity引擎的资源转换到Unreal引擎中进行使用。在资源转换过程中，我们需要处理四种类型的资源：地形、模型、纹理和材质。接下来我们分别介绍这四种资源的转换方式。 1. 地形资源 在原始的大场景动态加载案例中，我们使用的是Unity引擎的Terrain系统。但由于Unity与Unreal引擎中地形的数据格式不一样，因此我们无法直接在Unreal引擎中使用Unity引擎的地形数据。因此，我们尝试通过地形的高度图来将Unity引擎Demo中的地形转换到Unreal引擎中，其转换方式如下图所示： 我们首先对Unity引擎中的地形块导出高度图，然后将高度图导入Unreal引擎重建出相同的地形。高度图中的每一个像素记录的实际是地形块中每一个顶点在垂直方向上的高度。Unreal引擎中对于高度图的导入非常便利，如下图所示。在Unreal引擎高度图导入界面，我们只需在New Landscape界面中选择Import from File，并选中我们想要导入的高度图，再点击Import按钮即可导入高度图并重建地形。 但是，由于Unity与Unreal引擎的坐标系的不同，从Unity引擎中导出的高度图直接放入Unreal引擎中会导致重建出的地形与原始Unity引擎中的地形相对X轴呈现镜像的关系，如下图所示： 上图中左图是Unity引擎坐标系和原始地形截图，右图是Unreal引擎坐标系和重建地形截图。对于这种情况，我们可以做一个简单的坐标变换来让其看起来一致。但是，我们发现在Unity引擎中导出高度图时勾选Flip Vertically选项，也可以达到同样的效果，如下图所示： 其中，左图是Unity引擎原始地形，右图是高度图Flip后在Unreal引擎中重建出的地形。 在制作Unreal引擎大地形Demo时，我们不仅希望地形的形状与Unity引擎Demo一致，并且希望地形参数设置也尽量与Unity保持一致。在Unreal引擎地形参数中，主要包含了三个参数： Component Section Quad 这三个参数从上至下是包含关系，即：一块地形中可包含多个Component，一个Component可以包含多个Section，一个Section可以包含多个Quad。而Quad则是地形网格中最小的四边形。接下来我们分别介绍这三个参数的设置。 1.1 Component 在Unreal引擎的地形中，Component实际上是裁剪、渲染以及碰撞检测的基本单元。Unreal引擎在渲染地形时，一个Component要么被整体裁剪掉，要么被整体渲染出来并参与碰撞检测的计算。而其数量则是通过New Landscape窗口中的Number of Components参数进行设置，如下图所示： 其中，左图显示了New Landscape窗口设置界面，红色方框显示了Number of Components参数。该参数的设置可以任意选择，例如：1x1，1xN或者NxN。而我们在设置该参数时主要是参考Unity引擎大地形Demo的设置。右图显示了Unity引擎中地形的截图。在Unity引擎中物体裁剪是以GameObject为单位，而我们在制作地形时是以一块子地形作为一个GameObject。因此，在Unity引擎中地形的裁剪是以一块子地形为独立的裁剪单元。为了与Unity引擎Demo的设置保持一致，我们将Unreal引擎的地形设置中Component设置为了1x1，即一块子地形只包含一个Component。这样就保证了Unreal引擎中地形的裁剪也是以一块子地形为基本单元。 1.2 Section 在Unreal引擎的地形中，Section实际上是LOD的基本单元。它的数量可以通过Sections Per Component进行设置，如下图所示： 其中，一个Component中可以包含1（1x1）个或者4（2x2）个Section。该参数的设置我们也是参考了Unity引擎中地形的LOD。右图显示了Unity引擎中的一块地形网格截图。其中，右下角1/4大小的地形是比较密的网格，而其他3/4是比较稀疏的网格。因此，Unity引擎Demo中一个子地形块的LOD变化单元是1/4大小。所以，我们将Unreal引擎中的Section数量设置成2x2，即一个Component包含4个Section。这样可以保证地形的LOD变化粒度与Unity引擎地形基本一致。 1.3 Quad 在Unreal引擎的地形中，Quad决定了最后生成的地形网格的顶点数。其数量可通过Section Size参数进行设置，如下图所示： 其中，左图是Unreal引擎地形参数设置界面，右图是Unity引擎中地形分辨率参数界面。由右图可知，Unity引擎Demo中一块地形的顶点数是65x65。而Unreal引擎地形的Section Size参数则不能任意设置，只有几个选项可选择。因此，我们选择了最为接近的分辨率，如左图红框中所示。最终，我们重建出的地形的顶点数为63x63，如左图中蓝色框所示。 但是，虽然分辨率很接近，但问题还是出现了。由于我们在Unreal引擎中使用65x65分辨率的高度图重建出了63x63顶点数的地形，导致Unreal引擎在重建地形时对高度图进行了重采样。而重采样的结果造成了我们将子地形块进行拼接时，在相邻地形块之间出现了裂缝，如下图所示： 为了解决这一问题，我们对高度图进行了预处理。该预处理的目标有两个： 将高度图从65x65重采样成63x63； 保持相邻高度图的公共边的数值一致。 我们采用了如下的方法进行重采样： 如上图所示，左图表示重采样之前的高度图，右图表示重采样之后的高度图。在计算中间像素时，我们从原始高度图中选取周围4个临近的像素进行插值，如上图绿色框所示。在计算到边缘像素时，我们仅仅使用边缘上的两个像素进行差值，如上图红色方框所示。由于原始高度图中相邻边上像素的数值是一样的，而差值的过程中又保证了相邻边的采样点仅仅来自于边缘像素，所以保持了重采样后的高度图中相邻边的像素值一致。通过这个过程，我们得到了63x63分辨率的高度图，并且保证了其相邻边上数值一致。因此，我们在Unreal引擎中重建出的地形就可拼接完好，如下图所示： 其中，左图是原始案例中地形的网格截图，右图是Unreal引擎中重建出的地形拼接完成后的网格截图。 2. 模型资源 Unreal引擎中模型资源的导入非常便利，如下图所示： 我们只需在Content Browser窗口下点击Import按钮，然后选择需要导入的模型，并点击导入设置窗口中的Import即可导入。Unreal引擎中支持各种不同格式的模型导入，例如：FBX，OBJ等。 3. 纹理资源 Unreal引擎中纹理资源的导入过程与模型资源类似。目前来说，Unreal引擎支持绝大多数的图像格式，并且官方推荐使用的是PSD格式。 4. 材质资源 Unreal引擎中材质资源通常是使用Blueprint节点图进行编辑的。因此，我们在Unreal引擎中创建出材质Blueprint，并添加相应的纹理以及设置好参数。然后，将材质设置到对应的模型中，如下图所示： 其中，左图显示的是材质节点图，右图中红色方框显示的是将材质设置到相应模型中。 与模型材质不同的是，Unity引擎地形材质是通过将四张不同的纹理混合而成的。混合的参数则是通过一张Splat纹理中的RGBA四个通道分别指定，如下图所示： 其中，左图显示了Unity引擎中四张混合纹理，右图显示了纪录混合参数的Splat纹理。我们利用Unity引擎的TerrainData.alphamapTextures[ 由此，我们准备好了Unreal引擎中所需要的资源，并重建出了地形。接下来，我们需要将Unreal场景中的模型进行摆放和复原。 由于Unity与Unreal引擎的坐标系不同，所以我们要对其进行转换，如下图所示： 我们将原始场景中的所有GameObject的Transform信息制作成配置文件，然后通过一定的转换计算出Unreal引擎中Actor的坐标。由于Unity引擎中使用的长度单位是米，而Unreal引擎中使用的长度单位是厘米。因此，我们最终使用了如下的公式进行计算： 其中，左边是位置信息的转换，右边是旋转信息的转换，下边是缩放信息的转换。通过转换过的配置文件，我们即可在Unreal引擎中创建出与原始场景几乎一致的场景。 二、Unreal引擎场景流式加载 在重建了场景之后，我们接下来需要考虑如何对其进行动态加载。Unreal引擎为开发者提供了便利的场景流式加载方案，即Streaming Level。在Unreal引擎中，场景关卡主要分为两种：Persistent Level和Sub Level。Persistent Level在游戏启动时自动加载，并且会一直存在、不能被卸载。而Sub Level则可被动态加载和卸载。Streaming Level功能则使得我们能够很方便地动态异步加载、卸载Sub Level。在制作大地形动态加载时，我们只需将动态加载的内容分别放到不同的Sub Level中，就可利用Streaming Level进行异步加载和卸载了。 Streaming Level中触发Sub Level加载和卸载的方式有两种： Level Streaming Volume； Scripted Level Streaming。 Level Streaming Volume方式是利用在场景中摆放一个立方体，当Player进入该立方体空间内时，触发与该立方体绑定的Sub Level的加载。当Player离开该立方体时触发与之绑定的Sub Level的卸载，如下图所示： 其中，浅黄色的立方体方框即为Level Streaming Volume，深黄色矩形显示的是与之绑定的Sub Level中的一块地形。当玩家进出该浅黄色方框时，就会触发该地形块的加载和卸载。 Scripted Level Streaming则是提供了两个API：Load Stream Level和Unload Stream Level，如下图所示： 利用这两个API可以在任何时刻对指定的Sub Level进行加载和卸载。 这两种触发方式各有优缺点。使用Level Streaming Volume进行触发时，修改加载策略便利，但是触发方式单一。使用Scripted Level Streaming进行加载时，触发方式灵活，但是需要自己管理加载策略。 在使用Unreal引擎提供的Streaming Level功能制作大地形加载比较便利。我们的制作过程如下图所示： 我们在场景中创建出一系列的Level Streaming Volume，然后将其与对应的Sub Level进行绑定。在运行时，引擎便会自动根据玩家位置加载、卸载Sub Level。 上述为通过Unreal引擎内置的Streaming Level功能来制作大场景的动态加载，同样，也可以通过代码来进行实现，逻辑与上述一致，其具体实现细节就不在这里细表了。 三、移动端性能分析 通过以上两章说明，相信大家已经知道如何通过Unreal引擎来实现一个大型场景的动态管理功能。在本章中，我们将就Unreal引擎的性能效率来进行检测。对此，我们通过与之前在Unity引擎上的场景案例来进行真机性能对比，以期让大家对Unreal引擎的性能效率能有一个更为直观的了解。 在原始案例中，我们通过Unity引擎使用两种方式来制作了大地形的动态加载功能。一种是自己控制任何一块地形、任何一个地表物体（花、草、树和石头等）的流式加载和卸载；另一种是使用Unity引擎提供的Scene Manager功能进行实现，通过LoadSceneAsync和UnloadSceneAsync来进行地形块的加载和卸载。我们的制作方式如下图所示： 首先我们获取玩家的位置信息，然后根据玩家位置确定当前距离玩家最近的九个场景，最后利用Scene Manager API进行场景的加载和卸载。自己控制流式加载实现的过程也是类似进行管理。 但在性能对比时，我们更多的是使用自己实现的流式加载版本来进行对比，因为这是我们高度优化过的版本，其资源动态加载更为可控，从而性能较之SceneManager版本稍好一些，如下图所示。 在比较Unreal与Unity引擎制作相同大场景加载的性能时，我们对两个引擎的渲染参数进行了相同的设置。在测试过程中，我们选用Unity引擎的版本是2017.2，选用Unreal引擎的版本是4.18。同时，我们设置渲染的管线都是Forward Path，都不开启HDR和AA，Light Map都使用了Non-Directional。由于Unity引擎的Demo使用了饱和度颜色映射的图像后处理，因此我们添加了Unreal引擎自带的图像后处理饱和度映射，如下图所示： 其中，左图是Unity引擎的图像后处理设置界面，右图是Unreal引擎的图像后处理设置界面。我们分别从CPU性能、能耗和内存三个角度来进行分析。接下来我们分别进行介绍。 1. 性能比较 在性能比较中，我们比较了Unreal与Unity引擎Demo的FPS以及每帧耗时统计。在实验中，我们分别对比了Unity与Unreal引擎的PBR材质，以及Unity引擎Legacy和Unreal引擎PBR简化版的性能比较。这主要是因为在Unity 2017版本以后，地形系统的材质存在四种模式，如下图所示。所以，我们选择了Built In Standard和Built In Legacy Diffuse来进行测试。具体如下：在对比PBR材质时，Unity引擎中我们采用了Standard Shader进行渲染，Unreal引擎中我们使用了默认的参数设置。在对比Legacy和PBR简化版时，Unity引擎中我们采用了Legacy Diffuse材质，Unreal引擎中我们去掉了部分默认的PBR效果，例如：使用Full Rough，以及去掉Decal Response等。接下来我们将分别介绍它们的数据结果。 1.1 Unity PBR vs Unreal PBR default FPS 我们在高、中、低不同机型上进行了测试，下图分别为红米2、小米5X和三星S6上的FPS统计图： 其中，红色线条表示Unreal引擎的帧率统计，蓝色线条表示Unity引擎的帧率统计。从结果上看，在地形使用PBR材质时，Unreal引擎在红米2设备上帧率在15~25 FPS区间，在小米5X设备上帧率在40~55 FPS区间，而在三星S6设备上，Unreal引擎基本上可以达到满帧（60FPS）。同时，我们也可以看出，Unreal引擎在当前案例中的性能确实要领先于Unity引擎。 1.2 Unity Legacy vs Unreal PBR Simplified FPS 下图分别显示了红米2、小米5X以及三星S6上Unity Legacy Diffuse与Unreal PBR 简化版的FPS比较： 由上图可知，在地形使用Legacy材质时，Unreal引擎和Unity引擎在移动设备上的性能均明显提升。其中，Unreal版本在红米2设备上帧率在30~45 FPS区间，在小米5X设备上帧率在45~60 FPS区间。同时，我们也可以看到，Unity版本虽然还有一些掉帧情况，但在高端设备上性能有了大幅提升。 除上述设备之外，我们一共在8台不同档次的移动设备上进行了比较，其具体的帧率统计如下表所示。 由上图可知，在目前的高中低档设备中，Unreal版本（PBR简化版）的运行效率都相当优秀。除了红米Note2和魅族MX5两款机型外，Unreal引擎在本测试用例中的性能均高于Unity引擎。 2. 能耗比较 在能耗测试中，我们采用Unity Legacy Diffuse与Unreal PBR简化版材质进行渲染，并且将帧率固定在30FPS，然后使用高通Trepn工具统计实时功率。下图分别显示了红米2、小米5X以及小米5S机型上的统计数据，单位为毫瓦（mW）： 由上图可知，在中、低端机型上Unreal引擎的能耗比Unity引擎稍高，而在高端机型（小米5S）上，Unreal引擎要比Unity引擎高出许多。 3. 内存比较 在比较内存的试验中，我们采用Unity Legacy Diffuse与Unreal PBR简化版材质进行渲染，然后统计Android平台的PSS内存。下图显示了红米Note2机型上，Unity引擎自实现流式加载方式、SceneManager加载方式和Unreal引擎的内存统计，单位为MB： 由上图可知，使用Unity引擎 Scene Manager加载方式（灰色）的PSS内存会在一开始阶段随时间逐步上升，最后稳定在一个固定值阶段。这是因为Scene Manager加载方式在Unload场景时只是删除了GameObject而没有释放相关的资源，所以其内存会越来越多，直到场景遍历完为止。如果要释放该部分资源，则需手动调用UnloadUnusedAssets接口才行。而在我们自实现的流式加载版本中，我们通过UnloadAsset API来手动控制相关资源的卸载，因此，可以做到在整个场景遍历时，内存都维持在较低且平稳的程度上。而Unreal Streaming Level模式则会自动释放资源，其资源卸载是由引擎自动管理，因此Unreal版本在整体运行过程中，PSS内存也较为一致。 下图显示了更多机型上的内存占用。我们采用了Unity自实现流式加载方式与Unreal引擎比较，单位为MB： 由上图可知，Unreal引擎的PSS内存占用较之Unity引擎普遍较高。但其具体原因，我们暂时还无法给出解释，关于Unreal引擎底层的内存使用分析，是我们接下来计划重点研究的方向之一。 四、未来工作 以上则是我们近期对于Unreal引擎关于大地形动态加载的一些工作心得，相信读到这里的你，已经对开篇的两个问题——Unreal引擎中大地形的动态加载制作方法和在移动设备上的性能效率有了充分的答案。接下来，我们会在以下几个方面进行进一步的工作： 对Unreal引擎的内存使用进行深入研究，并对案例中的内存占用进行优化； 对Unreal引擎的CPU开销和能耗问题进行深入研究，并对案例中的性能进行优化； 将完善后的案例工程进行整理和开放，让更多的游戏开发者受益。 注：当我们第一次在真机上对Unreal的大地形版本进行测试时，完全被它的性能表现给震撼了。我们团队一直专注在游戏的性能优化方面，应该还算是有一定的技术积累，对于在何种设备上，何种复杂程度的游戏能跑出多大的性能数值还算是有些预判的。但当我们在红米2上运行我们自己做的Unreal版本时，心中的念头只有一个——“Unbelievable”！就目前而言，市面上Unreal移动游戏还相对较少，没有大量的项目可以让它在移动端进行充分的Tuning，但是，它展现出来的性能效果却大大出乎我们的意料。也许，这就是Unreal引擎这二十年来的技术底蕴，它让我们对于Epic这个单词产生了更加深刻的理解。 但是，需要郑重说明的是，该篇文章虽然比较了Unreal引擎和Unity引擎在真机上的性能效率，但是这并不能说明两个引擎哪一个更好。引擎之间的比较是多维度的，并且是无法从一个案例中得出结论的。因此，我们希望读者不要产生误解。在我们眼里，二者都是当今世界上伟大的引擎。无论是Unity还是Unreal，亦或是其他引擎，只要是能推动中国游戏进步的就都是好引擎！ 最后，感谢Unreal中国团队在我们案例制作和研究过程中提供的专业的技术支持！
在前期关于Unreal 4 引擎的技术推文中，UWA重点介绍了粒子系统的重点模块和高级功能。本文将进行介绍Unreal 4引擎中的新粒子系统：Niagara。需要说明的是，目前的Niagara粒子系统仍处于测试阶段，并非最终完成版。 这是UWA发布的第10篇Unreal 4技术文章，之前我们已经详细介绍过渲染系统、动画系统以及部分粒子系统的功能介绍，详情请转至UWA博客（blog.uwa4d.com）。同时，特别感谢Unreal中国团队对于本篇文章中Unreal引擎相关内容的审核，并在UWA团队学习其引擎的道路上提供的大力支持。 一、Niagara使用 1.1 开启功能 在最新的Unreal 4引擎中，Niagara模块已经被加入到引擎的插件中。需要使用时，只需通过菜单Edit->Plugin打开Plugin窗口，搜索”Niagara”并选择Enabled即可，如下图所示： 然后，在Content Browser中点击鼠标右键会出现新的菜单选项FX，该子菜单中包含了Niagara的各种资源选项，如下图所示： 其中，上图红色框中显示了Niagara中包含的各种资源：Niagara System为粒子系统资源，Niagara Emitter为发射器资源，Niagara Script为粒子系统逻辑脚本资源，Niagara Parameter Collection为参数集合资源。接下来，本文将分别对其进行介绍。 1.2 Niagara System Niagara System资源类似于Cascade中的Particle System资源。其创建方式可以通过右键菜单”FX->Niagara System”创建，将其拖入场景中时，引擎会自动创建Niagara Actor，并在其Niagara Component中引用该Niagara System资源： 其中，上图红色框显示了Niagara System资源，红色箭头表示将其拖入场景，蓝色框表示引擎生成的Niagara Actor，绿色框表示在其Niagara Component中引用拖入的Niagara System资源。 双击Niagara System资源可打开编辑器，如下图所示： 其中，上图红色框显示了Niagara System包含两个Niagara Emitter，在其区域内通过右键菜单可添加更多Niagara Emitter。Niagara System与Cascade的Particle System类似，可以包含多个Niagara Emitter，其执行顺序是从上至下。上图中绿色框显示了Niagara System的脚本节点图，其中包含两部分：Spawn和Update。Spawn只在该Niagara System初始化时执行一次，Update则会在每一帧都执行。从Niagara System的节点图中可知，其执行过程是顺序执行其包含的所有Niagara Emitter的Spawn和Update节点。 1.3 Niagara Emitter Niagara Emitter类似于Cascade中的Emitter。只是在Cascade中，Emitter的创建和编辑都在Particle System资源中，而在Niagara中它成为一个独立的资源。通过右键菜单”FX->Niagara Emitter”可创建该资源，双击该资源可打开其编辑器，如下图所示： 在目前最新的4.18.3版本中，新创建的Niagara Emitter会出现一系列报错信息。上图红色框显示了错误信息。同时打开Selected Emitter Graph窗口会发现Emitter的节点图默认情况下为空。此时可先点击上图中的一系列Fix Error按钮，引擎会自动添加相应的Module，并生成相应的节点图。添加完成后如果发现还有错误提示，可先关闭Emitter编辑器界面，重新打开，错误提示便会消失，如下图所示： 其中，上图中Emitter的Module设置界面中显示了6种不同类型的Module。设计者在这6种类型中添加不同的Module可以实现不同的粒子效果，其操作方式与Cascade中的Emitter添加Module非常相似。但与Cascade最大的不同点在于，Niagara中的这些Module除了可以使用引擎内置的之外，还可以使用设计者通过节点图编辑的自定义Module。而用户自定义节点图即为Niagara Script，本文将在后续内容中进行说明。 Niagara Emitter中不同块的Module执行时机也不相同： Emitter Spawn 表示Emitter Spawn时执行的Module，并且只执行一次 Emitter Update 表示Emitter Update时执行的Module，每帧都执行 Particle Spawn 表示Particle Spawn时执行的Module，并且只执行一次 Particle Update 表示Particle Update时执行的Module，每帧都执行 Add Event Handler 表示Emitter事件相关的Module Render 表示Emitter渲染相关的Module 打开Selected Emitter Graph窗口可以看到此时引擎已经自动生成了节点图，并且节点图分为上述不同类型，如下图所示： 其中，上图红色框显示了Set Particle Position节点，绿色框显示了该节点是用于在Particle Spawn时执行并输出结果。 而Emitter节点图正好对应了添加的Module，如下图所示： 其中，上图红色框显示了Emitter Module设置界面中Set Particle Position Module，绿色框显示了其属于Particle Spawn类型。 由此可见，Niagara的总体结构与Cascade十分相似，都是分为两层：单个Particle System可包含多个不同的Emitter，通过设置不同Emitter以及参数可实现不同效果。但Niagara比Cascade更为强大的是，它能让设计者自定义Module，其编辑方式为节点图。 1.4 Niagara Script Niagara Script在目前4.18.3版本中直接通过右键菜单创建会导致编辑器崩溃。绕开该问题的一个方式是先打开一个引擎内置的Script，然后将其另存为新的脚本，再进行编辑。为了使Emitter每帧都发射粒子，我们可以在Emitter Update中添加Spawn Rate Module，如下图所示： 其中，红色框显示了Spawn Rate Module，绿色框显示了目前发射的粒子数、Emitter的耗时以及所占用内存，通过该数据，设计者可以控制粒子的性能。双击红色框内的Spawn Rate即可打开该Script，如下图所示： 然后，将其另存为新的名字，即可创建出一个Niagara Script。在Niagara Script详细信息界面中可选择不用Usage来实现不同用途，其中包括：Module、Function以及Dynamic Input。分别表示该Script是用作Module，函数以及输入参数，如下图所示： Module Usage Bitmask参数表示如果该Script是当作Module使用，其使用的类型是哪些。该设置能够在Module设置时根据归类进行提示，并提供快速选择。Category参数方便对Script进行分类，在设置时可根据分类快速查找。 其中，上图红色框宣示了Module Usage Bitmask的选项。在上图中Emitter Spawn Script和Emitter Update Script被选中，因此在Module编辑界面添加Module时，在Emitter Spawn和Emitter Update两类中会出现该Script。 此时，我们虽然添加了Spawn Rate Module，使得场景中出现了粒子，但是默认情况下粒子为灰色，难以分辨。因此，我们将Render中的材质修改一下，便可看到预览场景中出现了该材质的粒子，如下图所示： 其中，上图红色方框显示了修改粒子材质为M_Spark。于是可在左图预览界面中看到粒子。为了让粒子动起来，我们还需在Particle Update类型中添加Update Velocity Module： 并且，修改Particle Spawn中的Set Particles Velocity Module的Velocity参数z为10.0： 即可看到粒子向z方向移动： 我们用上述方法实现了简单的粒子移动，但Niagara提供的功能和节点远不止如此。通过编辑节点图，设计者可以控制粒子发射以及运动的整个过程，从而可以实现任意想要的粒子效果。 二、Niagara与Cascade比较 总体来说，UWA认为Niagara粒子系统在功能方面的优势主要有以下两种： （1） Niagara提供了类似于BluePrint的编辑方式，从而使粒子系统的制作更加方便、更加灵活； （2） 不光对粒子发射器可以进行控制，同时让用户可以对粒子也可以进行控制，从而可以让用户自定义粒子的运动状态，进而制作出更为复杂的粒子特效。 当然，老版本Cascade粒子系统已经包含了大量常用的粒子系统效果。UWA认为，如果Cascade能够满足您的需求，则直接使用Cascade进行编辑即可，毕竟使用已有功能可以节省开发时间。而当Cascade中提供的功能无法满足需求时，则可考虑使用Niagara。设计者可以通过Niagara实现更加符合项目需求的、特殊的粒子效果。