UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - platform
时光流转，深耕不辍。UWA知识型栏目《厚积薄发 | 技术分享》已悄然陪伴大家走过459个工作周。在这一年的技术征途里，我们依旧扎根真实的游戏开发场景，以问答社区的经验沉淀为基石，又迎来了UWA AI技术的全新助力。 2025年的十大精选内容，既收录了社区开发者们互助探讨的智慧结晶，也融入了UWA AI基于海量知识沉淀的精准解答，每一篇分享都瞄准开发中的痛点卡点，为大家提供切实可行的破局思路。 回望这一年，是无数开发者的踊跃分享与积极互动，让技术的价值持续传递；展望2026年，UWA问答社区与UWA AI问答将继续并肩前行，以更专业的内容、更高效的解决方案，陪伴每一位开发者在技术深耕之路上稳步迈进！ UWA 社区主页：community.uwa4d.com UWA QQ群：793972859 From 问答社区 TOP1：如何让GameObject销毁时无论是否Active过，都调用OnDestroy？ 请教一个问题，MonoBehaviour的OnDestroy方法，如果这个GameObject的实例化时就是隐藏的，销毁时不会调用OnDestroy方法。我们项目有些核心逻辑是基于这个OnDestroy做的（时间太久远，耦合太多逻辑不好改出去了）。有没有什么办法，可以让这个GameObject销毁时无论是否Active过，都调用OnDestroy。 A1：要触发OnDestroy，必须要触发过Awake（Awake可以不明着写出来），通常是被实例化或者第一次激活的时候触发Awake，如果一直处于不激活的状态，那么销毁的时候不会自动触发OnDestroy。所以可以在激活的父节点上主动SetActive一下： A2：1. 一般一个Prefab本身是点亮的，大部分是里面的某些节点才会隐藏。如果是我说的这种情况，应该是在根Prefab摧毁的时候主动调用一次需要控制调用的子组件。 如果你真的是根Prefab就隐藏的那更简单了： （1）做一个工具扫描所有Prefab检查并且修改点亮情况； （2）编辑器模式下加载完一个Prefab之后检查是否点亮，如果没有则打印Error。 A3：我们也遇到了这个，主要导致的问题自定义组件清理不掉Lua注册过来的回调，导致返回登录报错。 我这边解决思路是，在脚本反序列化之后，将自己注册到UI根节点的管理脚本上，由这个管理脚本在Destroy时清理下面的子节点。Base脚本如下图： 有几个要点说明下： 我们只处理了UI（其他地方基本不会出这问题），项目的用法上每个UI根节点有必挂的组件，这个组件一定会执行Awake； 如果组件自身Awake走到了，就不需要额外的销毁管理，需要从管理器中将自己移除； 反序列化接口中有一堆限制，要小心处理，比如常用的接口只能在主线程执行，如果在子线程要跳过。还有Prefab打开的编辑状态也有一些状态取不到，我这边直接忽略了（因为不常用）。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/67d390183d306f3e9d594e7a From UWA AI 问答 TOP2：Unity中可以禁用GC吗？ Unity中可以禁用GC吗？ A：在Unity中，可以禁用垃圾回收（GC），但需谨慎使用，并结合具体场景进行管理。 禁用GC的方法 Unity提供了通过脚本控制垃圾回收器行为的API：GarbageCollector.GCMode。 该API支持以下三种模式： GarbageCollector.Mode.Enabled：默认模式，自动触发GC。 GarbageCollector.Mode.Manual：禁用自动GC，但可手动调用System.GC.Collect()或GarbageCollector.CollectIncremental()。 GarbageCollector.Mode.Disabled：完全禁用GC，包括手动调用也无效。 将GarbageCollector.GCMode设置为Disabled即可彻底关闭垃圾回收机制。 使用场景与最佳实践 禁用GC主要用于性能敏感的关键阶段，如战斗、加载、过场动画等，以避免GC导致的CPU卡顿（GC Spike）。 推荐做法： 预分配内存：在进入关键阶段前，预先分配所需的所有对象（如对象池、缓存等），确保运行时无新内存分配。 临时禁用GC：进入关键阶段时设置GCMode = Disabled，结束后立即恢复为Enabled或Manual。 手动清理：恢复GC后，调用System.GC.Collect()回收阶段性内存，防止堆持续增长。 示例流程： // 进入关卡前 AllocateLevelResources(); // 预分配资源 GarbageCollector.GCMode = GarbageCollector.Mode.Disabled; // 关卡运行中（避免任何new操作） // 关卡结束 GarbageCollector.GCMode = GarbageCollector.Mode.Enabled; System.GC.Collect(); // 回收内存 风险与注意事项 内存持续增长：禁用GC后，未引用的对象不会被释放，若持续分配将导致内存溢出。 必须严格控制内存分配：禁止使用字符串拼接、装箱、Linq、匿名函数等易产生GC的操作。 推荐结合0GC编程：使用StringBuilder、对象池、结构体等技术实现运行时零托管内存分配。 辅助优化手段 启用增量GC（Incremental GC）：在Player Settings中开启Use Incremental GC，将GC工作分摊到多帧，减少单次停顿时间。 性能监控：使用Profiler或UWA GOT工具监控GC Alloc值，定位内存分配热点。 综上，Unity支持运行时禁用GC，但应作为高阶优化手段，在可控内存分配的前提下短期使用，以换取更稳定的帧率表现。 From 问答社区 TOP3：为什么不应将游戏逻辑写在FixedUpdate中？ 请问在向别人解释不要把游戏逻辑放在FixedUpdate，而应正常地放在Update里，除了Input事件外，我还能使用哪些理由呢？ A1：FixedUpdate只处理物理相关的逻辑，Input事件应该放Update。 A2：如果卡，FixedUpdate会在一帧里执行多次来追上更新次数，可能导致严重的掉帧和发热。若想慢点更新，建议用携程或者用UniTask。 我需要一些硬性的不能做的理由，目前想到的就只有Input事件会重复或被跳过。 A3：那Update里面干什么?而且位置更新不放到Update和渲染匹配不上，看着应该会有顿的感觉。 A4：FixedUpdate不能动态锁帧，全放里面手机发热发烫耗电也快。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/677b429f682c7e5cd61bf9e4 From 问答社区 TOP4：InstantiateAsync有什么需要特殊处理的吗？ 请教个问题，InstantiateAsync有什么需要特殊处理的吗？我发现异步实例化出来的角色，好像丢了蒙皮一样，Mesh完全不跟着动画、还有根节点动，始终以T-pose的形态呆在固定位置，而且同一个角色，同步加载是正常的。 这是我这边的环境： A1：我们在接近你的版本和更高版本试了下，分别复现了问题和正常加载。查了下可能是类似下面的Unity Bug（异步实例化相关的bug有很多），应该要升一下版本。 A2：的确升级Unity版本后ok了。 A3：没啥问题，效果也比较好、明显，总得来说异步实例化好处多余坏处，我是调研过了并且项目在使用的。 AsyncInstantiateOperation.GetIntegrationTimeMS() AsyncInstantiateOperation.SetIntegrationTimeMS()可以设置异步实例化的间隔时间，默认是2ms，是Unity 2022.3.20新增加的功能。 写代码的时候可以考虑Async/Await，当然国际版Unity最新.3.60，国内版.3.54。 如果你项目没啥特殊可以考虑升级到最新，正常来说如果你没有上线最好到最新或者你得平时关注Unity版本发布日志。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/67ce97913d306f3e9d594e6c From 问答社区 TOP5：在Unity转微信小游戏下，如何用Worker实现多线程？ 想用WebWorker计算Unity里的小球的运动轨迹，请问Unity转微信小游戏的情况下，可以用Worker实现多线程吗？ A：可以参考官方文档：https://developers.weixin.qq.com/minigame/dev/api/worker/wx.createWorker.html 功能描述： 创建一个Worker线程。 参数： string scriptPath Worker入口文件的绝对路径 object options： 可选参数： 属性：useExperimentalWorker 类型：boolean 默认值：false 必填：否 说明：是否使用实验worker。在iOS下，实验worker的JS运行效率比非实验Worker提升数倍，如需在Worker内进行重度计算的建议开启此选项。同时，实验Worker存在极小概率会在系统资源紧张时被系统回收，因此建议配合worker.onProcessKilled事件使用，在Worker被回收后可重新创建一个。 最低版本：2.13.0 返回值 Worker Worker对象 注意事项 接口使用前需要在game.json（插件为plugin.json）中配置workers字段，表示Worker代码根目录。 scriptPath为入口文件的绝对路径，且不以/开头。 目前限制最多只能创建一个Worker，创建下一个Worker前请先调用Worker.terminate。 多线程Worker指南（小游戏）。 示例代码 // 创建普通worker wx.createWorker('workers/index.js') function createNewWorker() { const worker = wx.createWorker('workers/index.js', { useExperimentalWorker: true }) // 监听worker被系统回收事件 worker.onProcessKilled(() => { // 重新创建一个worker createNewWorker() }) } // 创建实验worker createNewWorker() 欢迎大家转至社区交流： https://answer.uwa4d.com/question/67c559603d306f3e9d594e69 From 问答社区 TOP6：增量GC机制，会导致碎片化更严重吗？ 请问增量GC这种频繁分配与释放的GC机制，会导致碎片化更严重吗？好像介绍增量GC的资料很少，所以有这种疑问。 A：对于碎片的产生，理论上增量GC和普通GC应该是没有什么区别的，都是标记-清除。增量GC只是把GC的工作分帧处理了，控制碎片的占用比例更关键的是要减少大块临时分配。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/684fe482682c7e5cd61bfaae From 问答社区 TOP7：为什么场景中没有刚体更无碰撞事件，但仍有较高物理耗时？ 我有个疑问：为什么GOT性能报告和Profiler里看物理模块耗时都很高？但其实这时候场景里已经没有刚体了，按理说不会发生碰撞，只有在代码里用了Raycast判断子弹命中，后来我把设置里的物理模拟关掉，又打了包，物理耗时确实降了下来，看子弹还是能正常命中（因为是代码调的），看粒子里的碰撞也还是能生效。 我不明白的是：之前那么高的物理耗时是在做什么？可能是什么导致的？是有一些我没留意到的地方用了物理导致的，还是说Unity机制如此？（Unity版本2022.3.59） A：的确，当前Unity版本的机制就是这样，很多时候必须要关闭掉物理模拟（指把Simulation Mode改成Script）才可以节省耗时。具体机制是场景中只要Static Collider数量大于0且没有关闭物理模拟就会有耗时，和场景中有没有刚体、有没有发生碰撞事件无直接关联。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/684688ea682c7e5cd61bfaa0 From 问答社区 TOP8：如何用GPU Instancing来优化树木草石重复模型？ 项目场景里的树木草石重复模型非常多，在尝试用GPU Instancing来优化。使用的Shader应该是SRP Batcher和GPU Instancing都支持的，但是材质勾上GPU Instancing后看FrameDebugger里还是走的SRP Batcher，要怎么修改比较好呢？ A：如果Shader两个都兼容，就会优先走SRP Batcher的。常规做法就是把规划要用GPU Instancing的物体用别的不走SRP Batcher的Shader；也可以考虑仍然用两个都兼容的Shader，但是用MaterialPropertyBlock打断SRP Batcher，这样就会顺延走GPU Instancing了。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/680dd4d53d306f3e9d594ecc From 问答社区 TOP9：如何在运行时获取硬件信息？ 请问怎样在运行时获取硬件信息？一般参考其中哪些信息进行分级比较合理？ A：一般是用SystemInfo里的一些接口，如图： 真机上输出效果如图： 一般用其中deviceType、deviceName去找对应的硬件档次划分；或者直接graphicsDeviceName给到的GPU型号进行画质分级。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/67f374e1682c7e5cd61bfa35 From 问答社区 TOP10：如何排查优化URP内置Shader冗余？ 请教一下Shader冗余应该怎么查，似乎好几个Shader运行时都有两份？ A：资源冗余最常见的原因是AssetBundle没有依赖打包导致的，可以使用UWA的在线AssetBundle检测进行冗余检测先试试。 测了AssetBundle，确实有冗余，但AssetBundle冗余的Shader和运行时冗余的Shader好像又不一致。实际运行时的冗余都是Hidden/Universal Render Pipeline/xxx。这又是为什么呢？ A：这些是URP的Shader，通常是URP Asset的引用导致的，因为URP Asset会引用这些Shader。而内存中出现两份Shader，说明内存中出现了两个来源路径不一样的URP Asset，通常一份是在PlayerSetting中引用的URP Asset，另外一份可能来自AssetBundle中动态加载的URP Asset。RendererData里面会引用到PostProcessData，PostProcessData就会引用这些Shader，如果代码里面动态加载的AssetBundle里面也有这种资源，也会引用一份Shader进内存，就会造成冗余。 请问这个怎么处理，直接删去吗？ A：一般只处理内存占用比较大的即可，其他的内存占用比较小，冗余开销也不大。比如Hidden/Universal Render Pipeline/Uberpost，需要删除其中用不到的Keyword来降低占用；又比如Hidden/Universal Render Pipeline/HBAO，看是否确实要用到，用不到就解除引用。 欢迎大家转至社区交流： https://answer.uwa4d.com/question/69245652244ce21ce9ec095c 无论是社区里开发者们的互助讨论，还是AI基于知识沉淀的快速反馈，核心都是为了让每一个技术难题都有解、每一次踩坑都有回响。本期分享分别来自UWA AI问答和UWA问答社区，希望这些从真实开发场景中提炼的经验，能直接帮你解决当下的技术卡点，也让你在遇到同类问题时，能更高效地找到破局方向。 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
为何iPad Pro上设置目标帧率为90时无法生效
1）为何iPad Pro上设置目标帧率为90时无法生效 2）为什么在Dedicated Server发布的程序中内存数值异常 这是第452篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 From 问答社区 Q1：为什么iPad Pro上设置目标帧率为90时无法生效，仍然以120帧运行？ 在使用Application.targetFrameRate设置目标帧率为90时，在iPad Pro M2芯片上无法生效，目标帧率变为120，在iPhone 14 Pro上测试则能够以80的帧率运行。 在和平精英上用PerfDog采集，可以设置为90的选项，实际以80的帧率在跑，但在Demo中测试无法达到同样的效果。 A：使用UWA AI问答的功能尝试解读这个问题。 分享链接： https://www.uwa4d.com/main/uwa-shared.html?shareId=f3ea7cc1-879f-4f94-aeb5-b29860099ae2 该问题通常由垂直同步（VSync）与帧率控制机制的交互导致，尤其是在高刷新率设备如iPad Pro上。 核心原因分析 在Unity引擎中，Application.targetFrameRate是控制移动平台帧率的主要方式。然而，当垂直同步（VSync）开启时，它会优先于targetFrameRate生效。系统会强制将应用的帧率锁定到屏幕刷新率的整数分之一（如120Hz、60Hz、40Hz等），以避免画面撕裂。因此，即使设置了targetFrameRate=90，系统也无法稳定输出非刷新率整除的帧率（90不是120的整除因子），最终会退回到设备支持的最高帧率（120fps）或下一个可行的分频值。 此外，部分iOS设备（尤其是支持ProMotion技术的iPad Pro）具有动态刷新率调节能力，其底层图形驱动可能进一步影响帧率锁定行为，使得targetFrameRate的控制不够精确。 解决方案 1. 关闭VSync并依赖 targetFrameRate 确保在项目设置或运行时关闭垂直同步： QualitySettings.vSyncCount = 0; // 关闭VSync Application.targetFrameRate = 90; // 设置目标帧率为90 这是实现非标准帧率（如90fps）最直接的方法。关闭VSync后，targetFrameRate将正常生效。 2. 使用引擎级帧平滑（Frame Pacing） 在使用虚幻引擎时，可通过CVar精确控制帧率。对于目标帧率90，在配置文件中设置： r.setframepace 90 此方法直接对接设备刷新周期，能更可靠地在支持的设备上实现90fps。 3. 验证设备与系统支持 确认当前iPad Pro型号及iOS系统版本是否完整支持90Hz的输出模式。某些情况下，操作系统或驱动可能限制了非标准刷新率的使用。 4. 监控实际帧率 使用UWA GOT Online报告中的“FPS均值”和“>40ms帧数占比”指标，结合真机性能测试，验证帧率是否真正稳定在90fps，并评估GPU负载与功耗表现。 综上，欲在iPad Pro上稳定运行90fps，关键在于关闭VSync并通过Application.targetFrameRate明确指定目标帧率，同时确保引擎和设备层面的支持。 Q2：如果已经关闭垂直同步，还可能是什么原因？ A：即使已关闭垂直同步（VSync），在iPad Pro上设置Application.targetFrameRate = 90仍可能无法生效，原因如下： 1. 动态刷新率机制（ProMotion）的底层限制 iPad Pro搭载的ProMotion技术允许屏幕刷新率在120Hz、60Hz、40Hz、30Hz等特定档位间动态切换。系统倾向于选择最接近目标帧率的标准分频值。由于90不是120的整除因子，系统可能无法为90fps创建稳定的刷新周期，最终退回到默认的120Hz模式。 2. Unity引擎的帧时间计算与平台适配问题 根据Unity文档，移动平台上的targetFrameRate实际效果受限于屏幕刷新率的整数分频。即使VSync关闭，Unity的帧调度器仍可能因无法精确匹配90Hz的间隔而出现抖动或回落至120Hz。此外，若未将targetFrameRate设置为屏幕刷新率的约数（如120 → 60, 40, 30），系统可能忽略该设置。 3. 后台进程或系统策略干预 iOS系统可能会因性能管理、温控或后台任务（如应用更新、索引服务）临时提升设备性能至最大刷新率，导致短暂脱离目标帧率。 解决方案 方法一：使用有效的刷新率分频值 避免设置非标准帧率，改用系统支持的分频： 若需高帧率，直接设为120 若目标为平衡性能与功耗，建议设为60或40 // 推荐做法 QualitySettings.vSyncCount = 0; Application.targetFrameRate = 60; // 稳定且兼容性最佳 方法二：通过Metal API或原生插件控制（高级） 利用iOS Metal框架的CADisplayLink精确控制渲染周期，绕过Unity默认调度，实现对90Hz的支持。此方法需编写原生代码，并确保设备支持。 方法三：验证并优化项目配置 检查项目是否启用了“Adaptive Frame Rate”等动态调节功能。 在UWA GOT Online报告中查看“FPS均值”和“>40ms帧数占比”，确认是持续120fps还是帧率波动。 使用UWA PA真机测试，排除模拟器或开发环境干扰。 综上，根本原因在于iOS硬件刷新率策略与Unity帧控制机制的不匹配。最稳妥方案是采用系统原生支持的帧率档位（如60fps），以确保稳定性与兼容性。 A2：iOS设备只能设置30的整数倍。 感谢123-619849@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6909d30d682c7e5cd61bfb64 From 问答社区 Q：在Dedicated Server发布的程序中，为什么在同一时刻Profiler.GetTotalReservedMemoryLong接口获得的数值会比Profiler.GetMonoHeapSizeLong接口获得的数值还小？ GetTotalReservedMemoryLong不是代表整个程序当前申请的内存大小吗？ 如上图： curValue - maxValue totalMemory:Profiler.GetTotalAllocatedMemoryLong() reservedMemory:Profiler.GetTotalReservedMemoryLong() monoHeap:Profiler.GetMonoHeapSizeLong() monoUse:Profiler.GetMonoUsedSizeLong() 引擎版本是2021.3.25f1c1。 A：使用UWA AI问答的功能尝试解读这个问题。 分享链接： https://www.uwa4d.com/main/uwa-shared.html?shareId=095aef95-daab-422c-ab95-acf6434f7892 在Dedicated Server（专用服务器）构建的程序中，观察到Profiler.GetTotalReservedMemoryLong()的值小于Profiler.GetMonoHeapSizeLong()，这看似矛盾，实则源于Unity内存管理机制和Profiler接口统计范围的本质区别。 核心原因：GetTotalReservedMemoryLong在非开发版中不可靠 最关键的一点是：Profiler.GetTotalReservedMemoryLong()等多数Profiler API在非Development Build（即Release或Server Build）中返回的是不完整或不可靠的数据。虽然文档指出部分内存API在Release版可用，但GetTotalReservedMemoryLong的行为在Dedicated Server环境下可能受限或未被正确维护。 相反，GetMonoHeapSizeLong和GetMonoUsedSizeLong是少数明确说明“即使在Release构建中也可用”的API，其数据相对可靠。 因此，你所观测到的reservedMemory (238MB)小于monoHeap (255-284MB)很可能是因为GetTotalReservedMemoryLong()返回的并非真实的总预留内存，而是一个被截断、未更新或仅包含部分内存池的值。 正确理解各指标含义： 为何monoHeap可能大于reservedMemory？ reservedMemory数据失真：如前所述，在Dedicated Server下，GetTotalReservedMemoryLong可能没有跟踪所有内存域（如图形、音频等子系统），或者其计数器未被激活，导致返回值偏低。 monoHeap是独立增长的：托管堆会根据内存压力动态扩容。当托管内存需求增加时，GC会请求更大的堆空间，GetMonoHeapSizeLong()随之增大。如果此时GetTotalReservedMemoryLong()因为Profiler限制未能同步更新，则会出现monoHeap > reservedMemory的现象。 专用服务器的优化配置：Dedicated Server通常禁用图形驱动、音频等模块，这些模块的内存池可能未被计入GetTotalReservedMemoryLong，但托管堆仍可正常增长。 建议的排查与监控方案 1. 避免依赖GetTotalReservedMemoryLong进行关键判断 在Release或Server Build中，该值不可信。 2. 使用更可靠的替代方案监控总内存 若目标平台支持，通过操作系统API（如Linux的/proc/self/status）读取RSS或PSS。 使用SystemInfo.systemMemorySize结合应用自身逻辑估算。 3. 重点关注托管内存趋势 定期调用GC.Collect()后获取GetMonoUsedSizeLong()，监控是否存在内存泄漏。 观察GetMonoHeapSizeLong()是否持续增长，判断是否需要手动触发GC或优化对象生命周期。 4. 在Development Build中验证 若条件允许，在开启Development Build的服务器上运行测试，对比各项内存指标是否符合预期。 综上，该现象主要由GetTotalReservedMemoryLong在非开发版中的局限性所致，应以GetMonoHeapSizeLong和系统级内存监控作为主要依据。 有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/68afb897244ce21ce9ec090d 无论是社区里开发者们的互助讨论，还是AI基于知识沉淀的快速反馈，核心都是为了让每一个技术难题都有解、每一次踩坑都有回响。本期分享分别来自UWA AI问答和UWA问答社区，希望这些从真实开发场景中提炼的经验，能直接帮你解决当下的技术卡点，也让你在遇到同类问题时，能更高效地找到破局方向。 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
导致Resources文件夹的资源在Android打包后丢失的原因
1）导致Resources文件夹的资源在Android打包后丢失的原因 2）GPU Culled Primitive中的xyz三平面剔除与视锥体剔除有什么区别 3）按照不升级Unity引擎小改动快速适配安卓16KB页面要求操作后还是闪退 这是第451篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 From UWA AI 问答 Q：请问Resources文件夹的资源在Android打包后丢失是什么导致的呢？有resources.load显式调用的。 A：Resources文件夹中的资源在Android打包后丢失，尽管有Resources.Load显式调用，通常并非资源未被打包进APK，而是由以下几种原因导致加载失败或资源无法访问： 1. 路径与大小写问题 Resources.Load的路径是不区分大小写的，但某些Android设备（尤其是定制ROM）的文件系统对路径敏感。如果代码中指定的路径与实际文件夹/文件名的大小写不完全一致，可能在部分设备上加载失败。确保路径字符串与Resources文件夹内的资源命名（包括嵌套文件夹）保持一致。 此外，路径应使用正斜杠“/”，且不包含“.asset”等扩展名。 2. 构建过程中资源被剥离或冲突 同名资源冲突：若项目中存在多个Resources文件夹，并且包含同名但不同内容的资源，Unity在构建时行为不确定，可能导致错误的资源被打包或覆盖。 Addressables或AssetBundle冲突：如果同一资源同时被标记为Addressable或打包进AssetBundle，又存在于Resources文件夹，可能会因构建流程混乱导致资源引用异常。建议避免资源重复管理。 3. 热更新或补丁机制干扰 使用Application Patching或自定义热更方案时，若处理不当可能导致StreamingAssets目录下原始资源被替换或删除。虽然Resources资源通常打包在主APK内，但在某些增量更新逻辑中，如果误操作了内部文件结构，也可能影响资源读取。 4. 安装路径变化（特定厂商手机） 部分国产手机（如华为、荣耀）将应用安装到SD卡时，路径中可能出现特殊字符（如 -），若项目中有自定义资源加载逻辑依赖路径拼接，未正确转义可能导致文件打开失败。虽然Resources.Load本身不受此影响，但如果涉及从外部加载补充资源并动态注册，则需注意。 5. 资源未实际打入包体 虽然Resources文件夹下的资源默认会被打包，但以下情况可能导致例外： 构建过程中出现异常中断，导致资源未完整写入。 使用了条件编译或脚本化构建流程，意外排除了Resources文件夹。 可通过解压APK文件（位于AndroidStudioProject/app/build/outputs/apk/或Unity导出目录），检查assets/bin/Data/resources.assets是否存在且包含预期资源，以确认资源是否成功打包。 排查建议 使用UWA GOT Online报告中的Resources.Load调用详情页，查看该资源的加载次数、耗时及是否返回null。 在真机运行时添加日志，捕获Resources.Load返回结果，确认是否为空。 检查目标设备的存储路径和安装方式，排除厂商ROM特殊行为影响。 清理构建环境，重新执行完整构建流程，避免增量构建残留问题。 综上，最可能的原因是路径问题或构建过程中的资源冲突，建议优先验证资源是否存在以及加载路径准确性。 分享链接： https://www.uwa4d.com/main/uwa-shared.html?shareId=88f1787d-7dc5-4d8a-91c2-09dc8d9c2258 From UWA AI 问答 Q：报告中的GPU Culled Primitive中的XY平面和Z平面剔除，和视锥体剔除是一样的吗？ A：GPU Culled Primitive中的剔除机制与视锥体剔除密切相关，但“XY平面和Z平面剔除”这一表述并不准确，实际并不存在独立的“XY平面”或“Z平面”剔除方式。通常所说的图元剔除主要指视锥体剔除（Frustum Culling），它是一种基于摄像机视锥空间的裁剪技术，判断物体是否位于可视范围内。 在图形渲染流程中，图元（如三角形）经过顶点着色器处理后，会进行一系列裁剪操作。其中，被裁剪掉的图元数量（culled_primitives）反映的是那些经过顶点计算后，最终因不在摄像机视野内而未被光栅化的图元。这部分图元的产生，主要受视锥体剔除机制影响 —— 即只有处于视锥内的图元才会继续后续渲染流程，其余则被剔除。 此外，还可能存在其他类型的剔除，例如： 遮挡剔除（Occlusion Culling）：用于剔除被其他物体完全遮挡的对象； 背面剔除（Backface Culling）：剔除面向摄像机背面的图元； 但这些通常不计入GPU图元输入统计中的culled_primitives主要部分。 根据本次运行数据分析，项目中图元处理情况良好，input_primitives与culled_primitives的比例处于合理范围，未发现因过度图元提交或严重剔除浪费导致的GPU顶点计算压力问题。因此，当前场景的剔除效率正常，无需针对图元剔除做额外优化。 综上，所谓的“XY平面和Z平面剔除”并非标准术语，实际起作用的是视锥体剔除，它是决定哪些图元被保留或剔除的核心机制之一。 GPU Culled Primitive中的“XY平面剔除”和“Z平面剔除”是视锥体剔除（Frustum Culling）在GPU硬件层面的具体实现阶段，它们共同构成了完整的视锥体剔除过程。 具体来说，视锥体剔除从逻辑上判断一个图元是否在摄像机的可视范围内（即视锥体内）。而在GPU执行时，这一过程被分解为多个连续的裁剪测试阶段： Facing & XY Plane Test：此阶段主要检测图元是否位于视锥的X、Y方向边界内，并进行背面剔除（Facing Culling）。若图元在X或Y轴方向超出视锥范围，或为背向相机的面，则在此阶段被剔除。 Z Plane Test：此阶段检测图元在深度方向（Z轴）是否超出近裁剪面（Near Clip）或远裁剪面（Far Clip）。若图元距离过近或过远，则被剔除。 Sample Test（微图元剔除）：进一步剔除那些屏幕投影面积过小、无法覆盖任何像素采样点的图元。 这些阶段按顺序执行，每一步都会统计被剔除的图元数量。因此，“XY平面”和“Z平面”剔除并非独立于视锥体剔除，而是其内部细分的裁剪步骤。 分享链接： https://www.uwa4d.com/main/uwa-shared.html?shareId=51a667fc-208e-4e0d-9d3d-a36a1bf2de39 From 问答社区 Q1：在UWA问答社区看到帖子： https://answer.uwa4d.com/question/68d4e378244ce21ce9ec0920 最近刚好我的项目也碰到了这个安卓16KB的问题，按照这个贴子实操还是一直闪退，想请教一下大家有碰到闪退问题吗，是如何解决的呢？ A：更新对应的so库，AS自己查看，不是显示16KB就得换，正常应该这么显示： Q2：这些都换了，谷歌的检测工具都能通过了，目前就是闪退。 A：很明显，假现象，工程里面绝对还有其它不符合标准的，可以空包一个一个往里面加就知道了。 Q3：我目前用2020版Unity出的空工程，按照上述操作完成之后，还是闪退，基本就没有其他的so。 A1：Unity得升级，最低是2021，升级到2022.3.系列，起码是2022.3.62，有些同大版本，都是不支持的，我问了一下Unity官方那边的人。 A2：试过不行，最后还是升到2022。 A3：可以分析一下闪退日志是否有报错，一般可以定位到问题库。 感谢小肥狼、tommom和小花轮子@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/68d4e378244ce21ce9ec0920 无论是社区里开发者们的互助讨论，还是AI基于知识沉淀的快速反馈，核心都是为了让每一个技术难题都有解、每一次踩坑都有回响。本期分享分别来自UWA AI问答和UWA问答社区，希望这些从真实开发场景中提炼的经验，能直接帮你解决当下的技术卡点，也让你在遇到同类问题时，能更高效地找到破局方向。 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
iOS框架内存中占用很高的ttc文件是否正常
1）iOS框架内存中占用很高的ttc文件是否正常 2）Constant Buffer在移动端的限制是多少 这是第448篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 无论是社区里开发者们的互助讨论，还是AI基于知识沉淀的快速反馈，核心都是为了让每一个技术难题都有解、每一次踩坑都有回响。本期分享分别来自UWA AI问答和UWA问答社区，希望这些从真实开发场景中提炼的经验，能直接帮你解决当下的技术卡点，也让你在遇到同类问题时，能更高效地找到破局方向。 From AI 问答 Q：用团结引擎Memory Profiler看iOS包的内存占用，这个可以定位iOS框架内存。发现里面有一个PingFang.ttc占用了74MB，不是在资源里，而是显示在iOS框架内存里面的，这个是正常的么？ A：该现象是正常的，无需过度担忧。 PingFang.ttc是苹果系统自带的苹方字体文件（TrueType Collection），属于iOS系统级资源。当应用首次使用系统默认字体（如在Text、TextMeshPro以外的UI元素中未指定字体）或系统进行文本渲染时，iOS会将该字体文件映射到应用的内存空间，因此在Memory Profiler的“iOS框架内存”或“Untracked Memory”部分中被统计为占用。 此部分内存由操作系统管理，不属于Unity托管堆或应用主动加载的Assets资源，因此不会出现在AssetBundle或资源列表中。其占用行为属于系统正常机制，且通常为共享内存（多个应用可能共用同一份字体数据的物理页），实际对整体PSS内存影响有限。 建议处理方式如下： 确认是否误用系统字体：检查项目中UI文本组件（尤其是Legacy UI Text）是否未指定自定义字体而依赖系统默认字体。若需统一视觉风格或降低对系统字体的依赖，建议使用嵌入式字体（.ttf/.otf）并打包至AssetBundle。 关注可优化内存区域：74MB的系统字体映射属正常范围，应优先关注Tracked Memory中的Managed Heap、Texture、Mesh等可控内存模块的优化。 避免不必要的文本渲染：减少动态生成大量文本对象的行为，合理使用对象池，防止因文本频繁创建导致系统字体缓存持续增长。 使用UWA GOT Online工具辅助分析：通过Resource模式下的内存自动采样，对比不同场景下PSS与Reserved Total的变化趋势，明确业务代码对内存的影响。 综上，PingFang.ttc占用74MB属于iOS系统正常行为，只要项目无异常卡顿或OOM崩溃，可视为合理内存使用。 分享链接： https://www.uwa4d.com/main/uwa-shared.html?shareId=29e9e0df-2c32-4b2e-9317-503e5891cfd8 From 问答社区 Q：CBuffer（Constant Buffer）在移动端一般大小限制是多少？ A：普通Shader的Constant Buffer，会受到Graphics API和硬件影响，可以用SystemInfo.maxConstantBufferSize获取。 通常除了GPU Instancing时，很难达到CBuffer的上限，所以一般不太关心这个，《Rendering 19--GPU Instancing》这篇文章里面有讲GPU Instancing的数量受到CBuffer的限制。 详见：《Rendering 19--GPU Instancing》第1.4 https://catlikecoding.com/unity/tutorials/rendering/part-19/ 原文如下图： 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/68d25f50682c7e5cd61bfb30 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
1）TextureStreaming针对不同分档机型一般怎么设置 2）不升级Unity引擎小改动快速适配安卓16KB页面要求 这是第447篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 无论是社区里开发者们的互助讨论，还是AI基于知识沉淀的快速反馈，核心都是为了让每一个技术难题都有解、每一次踩坑都有回响。本期分享分别来自UWA AI问答和UWA问答社区，希望这些从真实开发场景中提炼的经验，能直接帮你解决当下的技术卡点，也让你在遇到同类问题时，能更高效地找到破局方向。 From AI 问答 Q：想问问TextureStreaming的选项有没有推荐值，针对高中低机型一般怎么设置呢？ A：关于Texture Streaming的参数设置，需结合设备性能分级（高中低）进行精细化配置，以在画面表现与内存占用间取得最佳平衡。以下是针对不同机型的推荐策略： 核心参数说明 Memory Budget：纹理内存预算，决定Unity开始管理Mipmap加载的阈值。所有纹理（含非流式）均计入此预算。 Max Level Reduction：允许丢弃的最大Mipmap层数级数，优先级高于Memory Budget。例如设为2，则最多只加载Mipmap 2及更小层级。 Add All Cameras：默认开启，对所有摄像机启用串流。若需精细控制，可关闭并手动为特定摄像机添加Streaming Controller组件。 Renderers Per Frame：每帧处理的Renderer数量，影响CPU开销。建议根据帧率动态调整，避免卡顿。 高中低机型设置推荐 1. 高端机型 目标：追求极致画质，充分利用硬件资源。 Memory Budget：512MB~1GB（确保略高于 Texture.desiredTextureMemory）。 Max Level Reduction：0或1（尽可能保留高分辨率Mipmap）。 其他： 可适当提高Async Upload Time Slice和Buffer Size，加快资源上传速度。 启用streamingTextureDiscardUnusedMips = false，利用缓存减少重复IO。 优势：画面细腻，无明显纹理“popping”现象。 注意：监控targetTextureMemory，避免超出物理内存导致OOM。 2. 中端机型 目标：平衡画质与性能，控制内存峰值。 Memory Budget：200MB~300MB。 Max Level Reduction：1~2。 Renderers Per Frame：256~512（根据实际帧率微调）。 Async Upload： asyncUploadTimeSlice：4ms asyncUploadBufferSize：16MB asyncUploadPersistentBuffer = true 推荐做法：通过真机测试获取desiredTextureMemory，将Budget设为其1.2倍左右，留出余量。 3. 低端机型 目标：保障流畅运行，严控内存。 Memory Budget：100MB~150MB。 Max Level Reduction：2~3（强制降级，节省内存）。 Texture Quality：可配合使用“Half Res”模式进一步压缩非关键纹理。 Renderers Per Frame：128~256，降低每帧CPU开销。 强制代码开启： QualitySettings.streamingMipmapsActive = true; 避免编辑器设置在移动端失效。 关键点：UI纹理务必关闭Streaming Mipmap，因其无需远近LOD，开启反而浪费计算和内存。 关键实践建议 1. 必须代码开启Streaming 仅在 Quality Settings 中勾选可能在移动端无效，务必在启动时调用： SystemInfo.supportsMipStreaming // 先检测是否支持 QualitySettings.streamingMipmapsActive = true; 2. 真机测试为准 Editor中纹理内存远高于真机（路径不同），一切优化效果验证必须在目标设备上进行。 3. 合理启用对象 仅对场景模型贴图启用Streaming Mipmap。 UI、图标、不带Mipmap的纹理应关闭。 确保纹理开启Generate Mipmap且未勾选Read/Write Enabled（CPU内存不受Streaming影响）。 4. 动态调整策略参考 使用以下公式估算摄像机切换延迟最小时间： 最短延迟帧数 = (Texture.streamingRendererCount + RenderersPerFrame - 1) / RenderersPerFrame 结合Texture.streamingTexturePendingLoadCount判断是否完成加载，实现平滑镜头切换。 5. Lightmap支持串流 在Player Settings中启用Lightmap Streaming Enabled，同样受Budget与Max Level Reduction控制。 总结 最终配置应基于真实项目资源规模与目标设备Profile数据确定，建议结合UWA GOT Online报告中的纹理内存模块进行量化分析与迭代调优。 分享链接： https://www.uwa4d.com/main/uwa-shared.html?shareId=1d04bf11-027a-4d83-9ebf-f51f7c8a9407 From 问答社区 分享：不升级Unity引擎小改动快速适配安卓16KB页面要求 16KB Google Play兼容性要求 自2025年11月1日起，提交到Google Play且以Android 15及更高版本为目标平台的所有新应用和现有应用更新都必须在64位> 设备上支持16KB页面大小。 https://developer.android.com/guide/practices/page-sizes *上述网址需要使用VPN打开 Unity官方提供了升级引擎的方案： https://discussions.unity.com/t/info-unity-engine-support-for-16-kb-memory-page-sizes-android-15/1589588 如果项目还在使用古老的2018、2019等引擎不好升级怎么办？ 这里介绍一个方法： 一般Unity项目主要涉及以下几个so需要处理： libunity.so libil2cpp.so lib_burst_generated.so libmain.so 根据谷歌的文档，老版本NDK在链接so阶段需要传递以下参数即可完成适配： LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384" LOCAL_LDFLAGS += "-Wl,-z,common-page-size=16384" 那么我们逐个来看： 1.libunity.so 我们知道，项目勾选了Strip Engine Code的时候Unity是使用.a根据项目情况动态链接一个libunity.so出来的，所以我们很容易插入2这行，链接相关的参数对应的文件位于：PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\StaticLibs\arm64-v8a\link.rsp -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384 加入这两行即可。 2.libil2cpp.so IL2CPP支持自定义参数，可以通过以下函数实现增加链接参数： PlayerSettings.SetAdditionalIl2CppArgs("--linker-flags=\"-Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384\""); 调用一次即可，以上参数会保存在ProjectSettings.asset的additionalIl2CppArgs中。 3.lib_burst_generated.so 如果使用了burst，有条件的话可以直接升级到1.8.21+（参考以上官方链接），也可以自己魔改：使用dnSpy修改burst包.Runtime\Burst.Compiler.IL.dll的AotNativeLinkAndroid类的Link函数，添加那两行参数即可。 4.libmain.so 这个so是Unity已经编译好的，没法自己链接，好在它几乎没怎么改过，可以从已经支持了的高版本拷贝一个过来覆盖使用。 补充：上面解决的是so文件ELF的LOAD段的16KB对齐问题。 APK还存在2种模式： 新模式：安装应用的时候so文件不解压出来，so在APK中是不压缩的，这种情况是通过mmap直接将APK中的so映射到内存使用的。这要求两点：so本身16K对齐 + so在APK中的偏移也要是16K对齐。 旧模式：so在APK中是压缩存储的，安装时会解压so文件，这种情况只要求so本身对齐。可以通过useLegacyPackaging true开启，AndroidManifest.xml中extractNativeLibs会被设置为true。 https://developer.android.com/guide/practices/page-sizes#update-packaging *上述网址需要使用VPN打开 互动提问：不更换Unity版本，这块会不会有问题？ https://developer.android.com/guide/practices/page-sizes?hl=zh-cn#check-code A：目前未发现问题，游戏能正常运行。 互动提问：Unity 2019按上面步骤处理完，so 16KB对齐了，useLegacyPackaging=true，但在Android模拟器16KB镜像上，还是会崩溃，这是为什么？ A：模拟器应该是x86_64的，我是在Pixel9真机上跑的。 互动提问：按照方法处理后，AS分析APK后，lib中的.so库是正确了。但是AS依旧提示不支持16KB，这是为什么？ A：上面补充了一点信息，你的情况应该是上面的新模式了，这个还有个隐性要求：so在APK中的偏移也要是16K对齐，可以开启useLegacyPackaging试试。 感谢题主littlesome@UWA问答社区提供了回答，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/68d4e378244ce21ce9ec0920 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
1）将FGUI的Shader全部预热后，WebGL平台没有加载成功 2）iOS如何确认内存扩展使用生效 3）SpriteAtlasManager.atlasRequested延后一帧回调 4）Unity如何使用Java 17打包 这是第442篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 UI Q：将FGUI Unity中的Shader全部打包，全部加载预热后，Shader在WebGL平台没有加载成功，在WebGL平台FGUI的Shader都没有显示加载成功，请问是什么问题？在编辑器中加载包体预热，Shader是显示正常加载的。 A：FGUI添加Shader都是通过Shader.Find操作的，要让Shader.Find这方法能找到，需要执行以下操作之一： 从场景中使用的某些材质中引用它； 将其添加到ProjectSettings/Graphics中的“始终包含的着色器”列表中； 将着色器或引用它的对象（例如材质）放入“Resources”文件夹中。 感谢题主K了个O@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/689c51b6682c7e5cd61bfaf3 Platform Q：请问在iOS开发过程中，开启iOS的应用内存扩展功能后，是如何确认扩展功能生效的？目前我们在开启打包后进行使用感觉不生效，但是发布上线对外后又好像生效了。 A：如果是指的是Increased Memory Limit，该功能的生效对苹果设备和iOS版本都有一定要求。 可参考官网的说法： An increased memory limit is only available on some device models. Call the os_proc_available_memory function to determine the amount of memory available. Higher memory use can affect system performance. 具体是否生效、效果如何，可能就要看手头测试机内存加压测试中闪退阈值的变化；或线上实际闪退率了。 感谢Faust@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6896bfd4682c7e5cd61bfadd Editor Q：实测，触发SpriteAtlasManager.atlasRequested回调，比加载界面晚了一帧执行，导致会闪一帧白图。请教有何优化办法吗？图集已勾选Include in build。 A：Unity触发SpriteAtlasManager.atlasRequested时，AssetBundle系统还没初始化完毕，导致加载不到图集，进去后显示全白块了。因为我用的是YooAsset插件，这个东西初始化是异步的。只有下次触发SpriteAtlasManager.atlasRequested，才能再次加载图集，这可能是加载一个新的SpriteAtlas、或者加载场景时。 解决这个的方法时，在AssetBundle系统还没初始化时，SpriteAtlasManager.atlasRequested的请求先缓存起来，等初始化结束后再处理。 using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.U2D; namespaceGameCore.Unity { //场景一加载就会unity就会触发atlasRequested，但是这时候AssetBundle系统还没初始化，无法加载图集。 //因此等待AssetBundle初始化后加载。 //从编辑场景进入游戏的话，编辑场景里也挂载这个组件就行了。 publicclassSpriteAtlasLoader : MonoBehaviour { //缓存Unity的请求 privatestatic Dictionary<string, Action<SpriteAtlas>> requestAtlasCallbacks = new(); private IResManager resManager; //AssetBundle系统初始化后, 设置ResManager public void SetResManager(IResManager resManager) { this.resManager = resManager; foreach(var kv in requestAtlasCallbacks) { RequestAtlas(kv.Key, kv.Value); } requestAtlasCallbacks.Clear(); } private void OnEnable() { SpriteAtlasManager.atlasRequested += RequestAtlas; } private void OnDisable() { SpriteAtlasManager.atlasRequested -= RequestAtlas; } //AssetBundle系统初始化后，resManager不为null protected virtual void RequestAtlas(string atlasName, Action<SpriteAtlas> callback) { if(resManager != null) { callback(ResManager.Instance.GetAsset<SpriteAtlas>(atlasName)); } else { requestAtlasCallbacks.Add(atlasName, callback); } } } } 因为我有一个专门编辑Prefab的场景，可以直接从这个场景进游戏，因此单独做了一个组件，需要的场景里挂上就行了。 详情可参考《Unity SpriteAtlasManager.atlasRequested趟坑》。 感谢小泽@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/688757d2244ce21ce9ec08dc Platform Q：Unity如何使用Java 17打包，目前设置Java 17后Unity会提示错误，如何强制设置Java 17？ A：升级Unity版本或者用Unity导出AndroidStudio工程，在AndroidStudio中使用Java 17出包。 详情可参考《Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结》。 感谢hcg@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/682d72a9682c7e5cd61bfa7d 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
微信小游戏出现对应平台不支持纹理格式的问题
1）微信小游戏出现对应平台不支持纹理格式的问题 2）如何解决半透明物体穿插导致的渲染混乱问题 3）关于微信小游戏中玩家跑到未收集的函数时的相关问题 4）为什么升级到2022后会看到微信调试日志的堆栈信息 这是第440篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 Platform Q1：在微信小游戏似乎出现了对应平台不支持纹理格式的问题，请问下图中的报错具体是什么问题？ A1：应该是部分纹理用了DXT，但引擎编译时去掉了DXT转ASTC模块，所以要把所有图片转成ASTC。 感谢左君博@UWA问答社区提供了回答 A2：不过这样也不是最好的实现，如果要让PC表现的好，最好再出一份DXT的，在PC平台能指向特殊资源，移动端都用ASTC。 感谢肖海@UWA问答社区提供了回答 Q2：图集文件需要设置成ASTC吗？ A：是的。 感谢肖海@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6886f140682c7e5cd61bfacd Rendering Q：项目中大量半透明物体穿插，导致渲染序列混乱、合批失效，这种有什么比较好的解法吗？是不是需要确定每个半透明物体的先后顺序？ A：建议参考： https://blog.csdn.net/Strengthennn/article/details/147888022 感谢KYO@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6886edbc244ce21ce9ec08d3 Platform Q：在微信小游戏中，线上玩家第一次跑到未收集的函数会卡多久？第二个玩家跑到已有未收集的patch包大概额外需要多久？patch的大小限制是多少？ A：一个函数150～200ms，看缺了多少函数；缺失函数打到patch包里需要一分多钟。 感谢ruidawang@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6886ef75682c7e5cd61bfacc Platform Q1：我们项目是从2021升级到2022的，在2021微信调试日志是看不到栈的，但是在升级到2022之后，偶尔还是能看到日志的堆栈的，请问这个是正常的吗？ A：应该是勾上Profiling funcs就会有。 感谢左君博@UWA问答社区提供了回答 Q2：Profiling Funcs是否是必选？之前记得都没勾的，出问题了才关注起来。 A：Profiling Funcs对性能是无影响的，其实可以长期开着。 感谢肖海@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6886f2f9682c7e5cd61bface 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
1）UnityEngine.Object在失去引用后用什么方法销毁或回收 2）关于纹理采样方式对带宽的影响原理的问题 3）微信小游戏缓存catalog.json文件的方案 4）微信小游戏的帧率设置用哪个更好 这是第438篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 Memory Q：UnityEngine.Object在失去引用后，是一定要调用Destroy进行销毁么？不会被GC自动回收么？ A：UnityEngine.Object是一种基类，题主的问题比较大。常见的有三种情况： C#的托管堆内存在失去引用后，会在GC后被自动回收； 从AssetBundle中被加载出来的资源，需要用AssetBundle.Unload(True)这类的API定向卸载，或在失去引用后被Resources.UnloadUnusedAssets标记并卸载； 还有一种动态创建的对象，如通过new、instantiate生成的资源，则需要手动Destroy，或在失去引用后被Resources.UnloadUnusedAssets标记并卸载。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/686b545d682c7e5cd61bfaba GPU Q1：想问下关于纹理采样的消耗这块，有没有一些相关的经验可以分享？ 从Mali的文档上看，Cache Hit的情况下是1cycle采样1纹素，Cache Miss的情况下需要100-200cycle。 那么如果触发Cache Miss，是从当前采样UV位置的附近的2*2读取到Tex Cache上，还是直接读取L1大小的数据上去。比如Adreno有1KB的L1？ A：从Onchip到L1不是固定的2*2，也不是整个L1；根据GPU型号不同，有一个固定的每次取的大小，纹理压缩率越低、单个像素信息量越大，每次能取的像素数量就会更少，Cache Miss率就更高，此时就会往更远的L1、L2去取。 Q2：那是按1维去取n个像素，还是二维去取m*m个像素？想了解下怎么样摆放数据能Cache友好些。 A：应该是m*m。一般只要开启Mipmap，交由GPU自动选择合适的层级，就能使像素的采集过渡平滑友好，Cache Miss率较低了。此外就是尽量压缩纹理格式、避免使用各向异性这种大幅增加采样次数的做法，也能有效降低带宽。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/687476f2682c7e5cd61bfabf Memory Q：现在我们不能缓存catalog，每次需要临时下载还挺麻烦的。APP的Addressables热更的方案就是先去线上请求catalog.hash文件，然后判断本地的catalog文件是不是旧的，旧的就删除掉本地的catalog文件，然后下载新的。但是在微信小游戏会一直请求catalog，所以我们每次进入游戏都要下载catalog文件。请问微信小游戏该如何缓存catalog.json文件呢？ A：我的方案是自定义了catalog1000、settings1000文件，加上版本号，相当于是自己改了settings文件里面的catalog URL，然后改了catalog文件名，也改了Addressables的源码，取到版本号后去读取指定的settings文件，这样settings文件也可以缓存了。 我的方式是catalog和settings都自定义成了下面这样： 然后settings文件的这一句话改成了我指定的catalog1000： "m_InternalId":"{UnityEngine.AddressableAssets.Addressables.RuntimePath}/catalog1000.bundle" 再改了个Addressables的源码，Addressables在初始化的时候会去找settings文件： 然后就是走微信小游戏自己的规则了，即本地有就读取本地，本地没有下载缓存。catalog和settings都加了版本号，也不怕settings同名或cdn缓存问题。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/687482d6682c7e5cd61bfac0 Platform Q：微信小游戏现在都是推荐用Unity的Application.targetFrameRate了吗？现在我们用的这个WX.SetPreferredFramesPersecond，会产生什么问题吗？没Unity那个性能好？ A：帧率设置可能失效。现在微信小程序已对Application.targetFrameRate做了较好的适配。 更推荐用这个： https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/issues/713 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/6874a85b3d306f3e9d594f11 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
1）增量GC机制，会导致碎片化更严重吗 2）有没有关于Collider的性能差异分析经验 3）如何利用system.info返回的信息自动切换qualitylevel分级 4）如何设置Unity的两种网格数据压缩方式 这是第436篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 Script Q：请问增量GC这种频繁分配与释放的GC机制，会导致碎片化更严重吗？好像介绍增量GC的资料很少，所以有这种疑问。 A：对于碎片的产生，理论上增量GC和普通GC应该是没有什么区别的，都是标记-清除。增量GC只是把GC的工作分帧处理了，控制碎片的占用比例更关键的是要减少大块临时分配。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/684fe482682c7e5cd61bfaae Physics Q：请问有没有MeshCollider和BoxCollider或者SphereCollider具体性能差异的分析经验？ 我们项目有比较多的UGC内容要用到很多Collider，之前项目的经验是基本不用Mesh，全是CapsuleCollider和BoxCollider。但是确实没有定量的性能差异的分析，正好有机会想重新评估下方案。 A：有条件的话在项目拟真环境下对比测试是最好的。 如图测试，仅供参考。200个球不停的碰撞，MeshCollider耗时均值为11.6ms，SphereCollider耗时均值为8.0ms，测试手机是OPPO R17。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/684fe3c7682c7e5cd61bfaad Platform Q1：请问如果要用system.info来自动切换qualitylevel分级，通常会建议用哪一个system.info的值来检查？ A：我们项目的做法是以GPU的算力为主，基于GPU型号来得到区分高中低档设备的基准，在此基础上结合了其它分档要素和项目要用的渲染效果或额外功能作为Feature，自己做一个评分表格来划分高中低档位。在后续维护中，市面上有新设备或项目要下沉市场，都是得不断更新这个表格里面的GPU型号的。 Q2：GPU型号具体是指哪一个? 算力是指GPU的最大频率对吗？ A：是graphicsDeviceName这一条。算力不能光看GPU频率，需要查看整体算力，一般可以直接参考GPU算力天梯网站给的分数，有条件的话辅以一些实验测试微调。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/684fbd9f682c7e5cd61bfaa9 Memory Q：请问项目的Vertex Compression，以及模型的Mesh Compression分别怎么设置比较好？分别对存储、内存、性能以及效果是怎么影响的？ A：经测试，Mesh Compression开启可以减少打包AssetBundle的大小，但是不会改变Mesh在运行时的内存占用；Vertex Compression开启可以减少Mesh的运行时内存，但是如果对应的FBX开启了Mesh Compression，则Vertex Compression会无效。 针对以上问题，有经验的朋友欢迎转至社区交流： https://answer.uwa4d.com/question/684fba3b3d306f3e9d594ef9 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859
如何优化微信小游戏在iOS机器上Shader变体预热特别慢的问题
1）如何优化微信小游戏在iOS机器上Shader变体预热特别慢的问题 2）小游戏进程的包内存不足问题 3）微信小程序并发下载请求的具体限制 4）对于Wwise有什么优化经验 这是第434篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 Platform Q1：请问微信小游戏在iOS机器上Shader变体预热特别慢，这个有什么优化方向吗？以我们项目来说，安卓用时1秒多，iOS稳定10秒。 A：团结引擎里面有异步的Warmup操作，Unity引擎里面没有这个功能，可能需要考虑进一步减少Shader变体数量，或者分批次Warmup。 可参考： https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/AsyncShaderWarmup.md https://docs.unity.cn/cn/tuanjiemanual/Manual/WeixinAsyncShaderWarmup.html Q2：已经试过了，把团结引擎升级到了最新，然后联系微信的人开通了测试权限，现在流程是跑通了，但是测试下来结果并不理想。虽然现在是异步了，但是会影响主线程的其他东西加载，用的总时间反而比以前更久了。 开启异步时，帧率只有2，但它的作用只能是它在加载的时候，不要去干别的，这样确实不会卡住，但凡做点事情就不行了。请问还有什么其他的办法吗？ A1：建议用Unity Profiler连着看Timeline，就是连上Profiler，找到有Shader.CreateGPUProgram耗时的那一帧，切换到Timeline模式，找到Shader.CreateGPUProgram的那个耗时，鼠标放上去应该可以看到具体是哪个变体的耗时这么高。 A2：找到原因了，就是这个导致的： 感谢Faust@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/683e6804682c7e5cd61bfa97 Memory Q1：Unity 2021.3.23f版本，用wasm分包。看的是自身小游戏的进程，用WebContent。在iOS 18.4的版本崩溃率很高，表现就是一打开就秒显示包内存不足，实际内存在Mac上的Activity Monitor看，进程一直是700~800m。有时候要连续崩溃几次就能正常进游戏。请问这是因为什么导致的呢？ A：这是iOS 18.4的Bug，要解决这个问题建议换一个设备，或者使用分包的方法，因为18.4上wasm的编译内存会比较大，所以建议分包。 感谢左君博@UWA问答社区提供了回答 Q2：请问线上版本如何确定有没有用到wasm分包，通过后台或者日志能看到吗？ A：你扫码启动游戏，打开vConsole就能看到。 感谢ruidawang@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6833ffb73d306f3e9d594ee4 Platform Q：请问微信小程序目前的版本最多支持多少个并发下载请求？ A：具体限制看这里： https://developers.weixin.qq.com/minigame/dev/guide/base-ability/network.html 感谢袁梓民@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/683e64ed682c7e5cd61bfa95 Memory Q：请问大家对于Wwise有什么优化经验么？或者可以推荐阅读内容么？主要想了解下其他项目是怎么使用的，比如动态管理方面。 A：关于内存方面的优化，可以参考官方文档： 《Wwise SoundBanks内存优化》 《wwise内存问题》 《关于降低内存占用的技巧 》 其中最常规和效果显著的做法是比较类似引擎原生音频的优化方法，如流式加载、控制压缩率和采样率。也还有从策略上进行优化的方案。 感谢Faust@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/683e68d33d306f3e9d594eeb 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859