UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - ios
type: channel
link: https://blog.uwa4d.com/tag/ios/
items: WorldSpace下的合批策略与ScreenSpace有什么区别
items: 限制Unity帧率的方式
items: 2D项目大量物品图标Draw Call优化方案
items: SRP Batch合批失败
items: DLL混淆问题
items: TextMeshPro备用字体疑问
items: Lua与C#传参
items: 带多个Submeshes模型合并，显示​异常
items: Unity Batches与glDrawElements的关系
items: 开发期资源管理的策略选择

WorldSpace下的合批策略与ScreenSpace有什么区别
type: item
date: 2024-05-21T04:54:00+03:00
description: 1）WorldSpace下的合批策略与ScreenSpace有什么区别 2）在iOS上用Metal取代OpenGL的多么 3）在动画蓝图中将两个或多个动画同时融合到同一个网格 4）Mipmap如何限定层级 这是第387篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：793972859 UI Q：WorldSpace下渲染Prefab做的HUD，如果只显示同一张图片，可以合批，如果再显示一个TextMeshPro， 直接全部都不能合批了。 【UGUI疑问】WorldSpace下的合批策略与ScreenSpace有区别吗？ 针对以上问题，有经验的朋友欢迎转至社区交流分享： https://answer.uwa4d.com/question/6645d42c5ce8a46b00fc4d3f iOS Q：苹果官方早就宣布放弃OpenGL了， 所以这年头用Unity开发iOS的用Metal取代OpenGL的多么？ A：苹果的软硬件统一要求非常严格，为了支持新的iOS系统和手机、包括方便渲染性能分析调试的话，现在应该普遍都是用Metal的了。 感谢Faust@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6642c9595ce8a46b00fc4d35 Animation Q：需要明确的是，当我按下游戏手柄或控制器上的按钮X时，会播放按钮X的动画。如果我按下按钮Y并仍然按住按钮X，我希望看到两个按钮的动画同时播放，而不仅仅是一个动画。 我正在使用一个装配好的手柄和控制器网格，带有动画蓝图，使用状态机来调用和播放动画。 我已经在AnimGraph中尝试了几乎所有不同的混合节点。但是，只播放动画一（混合权重1）或动画二（混合权重2）。如果我设法将两个动画混合在一起（混合权重0.5），则会播放按钮x和y的动画，但只播放动画的一半。 请问，有没有办法在动画蓝图中将两个或多个动画同时融合到同一个网格（不同的骨骼）上？ A：使用Layered blend per bone，并在细节面板的图层设置中为每个混合姿势设置一个关节。 这样你就有了每个关节的Alpha值，并且动画可以与其他动画一起用于单个关节。 复现： 在ABP中用Layered blend per bone来组合不同的动作，上面的是主动作，下面是要叠加的动作。 在Layer Setup中设置受控制的关节名称。 这样就可以两个动作叠加在一起了。 针对以上问题，有经验的朋友欢迎转至社区交流分享： https://answer.uwa4d.com/question/664582e85c7f5d2c5805d3e3 Memory Q：请问Mipmap如何限定层级？ 比如一张1024x1024纹理，共有Mipmap0~10，但是项目只用到Mipmap0~2，如何省略掉3~10？ A1：用Texture2D.minimumMipmapLevel试试。 感谢vTHu9nLdTLZM@UWA问答社区提供了回答 A2：Texture Streaming理论上可以让你更节约一点点。 感谢王林@UWA问答社区提供了回答 A3：用mipCount这个参数试试。 new Texture2D(width:256, height:256, textureFormat:TextureFormat.ARGB32, mipCount:3, linear:true) 感谢给个30K的资深titleba求求了@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/65c0a61340a8d93b624afccc 封面图来源于网络 今天的分享就到这里。生有涯而知无涯，在漫漫的开发周期中，我们遇到的问题只是冰山一角，UWA社区愿伴你同行，一起探索分享。欢迎更多的开发者加入UWA社区。 UWA官网：www.uwa4d.com UWA社区：community.uwa4d.com UWA学堂：edu.uwa4d.com 官方技术QQ群：793972859

限制Unity帧率的方式
type: item
date: 2024-02-06T03:57:00+02:00
description: 1）限制Unity帧率的方式 2）只在编辑器内，纹理不开启Read&Write情况下，如何获取纹理所有颜色值 3）如何在FBX剔除Lit.shader依赖 4）如何在iPhone 12mini设备上禁止竖屏 这是第373篇UWA技术知识分享的推送，精选了UWA社区的热门话题，涵盖了UWA问答、社区帖子等技术知识点，助力大家更全面地掌握和学习。 UWA社区主页：community.uwa4d.com UWA QQ群：465082844 Platform Q：目前我们想把游戏设置为30帧，是通过Application.targetFrameRate实现的；但是会有一些兼容性问题，比如一些设备会动态调整设备刷新率导致游戏帧率过低（比如设备从120HZ动态降为60HZ时，游戏就从30帧掉为15帧了），我们也尝试过跟进设备的刷新率变化动态调整Application.targetFrameRate，但是一些设备还是出问题，主要是一些支持高刷新的设备，如120HZ、180HZ，设备在标准模式下本身会动态调整刷新率的，节约能耗。 不知道大家有没有相关的经验或者更好的解决方案？ A：可以尝试挂一个Update脚本，估计可以跟上高刷新的设备120HZ、180HZ的动态调整刷新率。 感谢NG週@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/65bb481a3625c22cffcb1df0 Editor Q：只想在编辑器内优化一些纹理图片，纹理不开启Read&Write。 目前方案如下，但是会有几个问题： 1. LoadImage只支持PNG、JPG格式，像TGA、PSD格式则返回为空。 2. 对于那些几十MB的PNG纹理，也是返回空。 请问有无其他方式？ 代码如下： var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath); var bytes = File.ReadAllBytes(assetPath); var new_texture = new Texture2D(texture.width, texture.height); var res = new_texture.LoadImage(bytes); if (res == false) { Debug.LogError($"错误提示：{assetPath}纹理资源LoadImage失败", texture); return null; } var colors = new_texture.GetPixels32(); // 获取到所需颜色数组 A1：可以试试以下方法： Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath); // 你的纹理 byte[] rawTextureData = texture.GetRawTextureData(); Texture2D finalTex = new Texture2D(texture.width, texture.height, texture.format, false); finalTex.LoadRawTextureData(rawTextureData); finalTex.Apply(); var colors = finalTex.GetPixels32(); // 获取到所需颜色数组 请注意，所有这些方法都是在绕过Read/Write Enable的限制时的替代品，而不是直接的解决方案。如果可能，最好还是在导入纹理时启用Read/Write Enable以获得更好的性能和更简单的纹理操作。 另外一个方法：可以设置一个Camera的TargetTexture为一个RenderTexture，接着使用Graphics.Blit将目标纹理渲染到这个RenderTexture上。然后，你可以通过ReadPixels函数将RenderTexture读取为Texture2D。这种方法不依赖于Read/Write Enable。 扩展阅读：《高效访问纹理数据，持续优化整体性能》 感谢NG週@UWA问答社区提供了回答 A2：我之前用过@NG週说的办法，是可行的，不过我当时只处理PNG图片。 另外离线处理纹理，可以考虑使用Job来并行化处理，效果很高。 感谢junbin.liu@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/65b320393625c22cffcb1de5 Asset Q：测试发现只能通过后处理才能去掉Lit.shader依赖，尝…

2D项目大量物品图标Draw Call优化方案
type: item
date: 2022-02-28T12:05:00+02:00
description: 1）2D项目大量物品图标Draw Call优化方案 ​2）UGUI SpriteAtlas的热更新问题 3）iOS平台突然有一帧UI渲染开销很高 4）iOS上频繁Crash，堆栈很奇怪 这是第288篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Rendering Q：我们有个2D项目，大致布局如下图： 1.场景按格子划分，玩家可以在每个格子上面摆放物品，物品种类非常多（700+）。 2.部分物品还有动画效果，动画会改变该物品的材质属性。 3.物品图标的大小不是严格一个格子大小，因此会有部分物品图标间的重叠。 4.场景的视角可拖动，最远视距下可以看到超过100个物品。 5.场景上除了物品，还有云雾、水波、发光粒子等各种特效。 具体实现： 1. 场景底图采用美术分割方式，每张2048*2048大小，由16张组成，直接使用SpriteRenderer摆放渲染。 2. 物品图标每张256以内，同样采用SpriteRenderer摆放渲染。 3. 使用Unity内置渲染管线。 经过一番Profile，发现目前主要性能问题在于Drawcall数量非常大，没摆满的情况下都接近300，主要消耗点在于特效跟物品图标的渲染。 1.由于物品数量巨大（后续还会增加），目前采用SpriteAtlas方式把所有物品图标进行合图，会产生3张2048*2048尺寸的图集，各个物品可能会随意分散在这3张图里，加上物品穿插显示，导致无法合批。 2.物品有状态，不同状态会对材质属性进行变更，改变灰度明亮度等效果，导致无法合批。 3. 场景上的粒子特效是3D的，会随意在物品图标中移动穿插，导致图标无法合批。 已经考虑过，但否决了的方案： 1.把图标缩小，使生成的图集在一张2048以内。 => 询问过策划，物品种类目前还不是全部的，完整的配置里有超过1000+物品，都合成到一张2048里不现实。 2.图标不合图集，直接散图集成，采用运行时动态合图方式对场上物品进行合图。 => 游戏主要玩法会导致不停拖动物品图标以及旧物品的删除跟新物品的生成，操作会非常频繁，动态合图方式消耗巨大。 鉴于上面所描述的状况，各位大佬有没有什么推荐的优化方案？ A1：可以从以下方式入手： 首先图片和图集减少Draw Call没问题，图集也应该做分类，把能组合的类型分配并归类。图集不是追求少就好，应该是动静分离，还有按项目分类。做到图集数最优，这个就要结合自己的项目分析了。 然后合批的问题要解决。重写一个Shader，挂载到SpriteRenderer上，改变这个材质上的属性可以避免导致无法合批。 格子布局应该避免元素重叠，这个在设计就要避免的。粒子特效尽量用2D效果来做表现，粒子的发射数量与粒子数量也要做权衡。 感谢廖武兴@UWA问答社区提供了回答 A2：建议动态图集，静态图集在这种情况下，基本是负优化。 感谢uwa菜鸡奶泡泡.@UWA问答社区提供了回答 A3：这个问题，其实挺好解决。 1.背包的物品组件做一个循环动态列表功能，这样同屏加载不会很多。 2.物品的同一个组件进行拆分，比如bg一个图集， icon一个图集，数字图片一个图集，特效纹理一个图集。 这样下来DrawCall一般在三四个可以搞定。 感谢郑佳宇joe@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/6215b229e7172c2775f6f5c6 Atlas Q：UGUI图集切换后，图集中的图片名称不变，只是改变该图片为其他图片，但是为什么在加载UIPrefab的AssetBundle之后，UI上对应修改的图片会出现白图？会发现SpriteAtlas的CanBindTo返回false。 A：替换图片时，不修改原GUID则可以避免这个问题。 感谢题主Austin@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/621c3e1be7172c277500573d UGUI Q：iOS平台通过Profile定位性能，偶现某一帧UI开销异常高，通过Timeline看到是Render引起的，但是不知道后续应该如何定位。 这里可以看到这一阵Render开销达到了12.35ms，其他帧只有不到2ms。 A：EmitWorldScreenspaceCameraGeometry（图中紫色）这个函数是UGUI的Canvas网格重建生成UI Draw Call的开销，主要工作在Native子线程进行，主线程表现为该函数的等待开销，建…

SRP Batch合批失败
type: item
date: 2022-01-19T10:18:00+02:00
description: 1）SRP Batch合批失败 ​2）Unity增量打包AssetBundle没变化的资源也会被重新打包 3）如何查找il2cpp.so代码段映射的内存突然变大的问题 4）iOS画面不明原因freeze 这是第283篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） SRP Q：最近尝试用SRP Batch，但感觉非常难以捉摸。这里所有的物体都是用的同一个Shader，而且关键字也都一样，也就是同一个变体。按说应该可以合并Batch的，但第二个提示Shader的关键字不同，SRP合并失败。 在网上查了一些资料，没有有用的信息。自己试了一下，只要改其中的一些RenderQueue，SRP Batch的结果就有变化（不能合并的数量变少了）。 但是，RenderQueue不能随便改吧？会影响性能。而且对于半透的来讲，渲染结果都会错。更何况改起来非常麻烦。各路大神们，想了解一下大家是怎么解决这个问题的？另外，大家的项目有没有用SRP Batch？还是用的传统的Static Batch？ 有人提醒，把光图去掉试试，虽然的确有用，但总不能去掉光图吧？ 又试了一下，专门把这些结点单独烘一下，也有用。看来跟光图也没直接关系。 A1：这个应该是mat序列化文件里残留的关键字导致，Unity的Bug。 比如说：美术先用创建一个材质a，用的lit shader，调整自发光设置，导致材质里多了一个关键字_EMISSION，然后美术把这个材质改成了自定义Shader。这时候就算你的自定义Shader里没有_EMISSION这个关键字，材质的序列化文件里还是会记录下来。 然后再创建一个材质b，和材质a属性完全一样，只是没有残留的关键字_EMISSION，你会惊讶的发现材质a与材质b不能SRP Batcher，原因写：Node use different keywords。并且这时候你用Frame Debuggger去看这两个材质的DrawCall，你是看不到_EMISSION这个关键字的，因为实际上确实没用到。 感谢deviljz@UWA问答社区提供了回答 A2：感谢回复，确实是mat文件里存储的关键字导致的问题，如图： 修改关键字后，两个SRP Batch变成一个了： 另外，补充一下，之前说的改RenderQueue就能解决部分问题，中间确实是这样。但后来经过测试，我把整个的光图重新烘了一下，问题就解决了。中间做了什么已经不清晰，原因未知。不过，半透的东西我还需要再确认一下是不是改keywords就没问题了。 现在大致摸到门路了，如果Batch和Batch之间上下紧挨着，变体又是一个，就是关键字的bug问题。如果并不是紧挨着，变体虽然是同一个，也不能合并Batch。这时，需要先调整RenderQueue，让它们渲染次序紧挨着，Batch才可能会合并，和NGUI调整图层可以优化性能意思差不多。 其实只要把材质使用的Shader里没有的关键字删除就可以了： public static void RemoveRedundantMaterialShaderKeywords(Material material) { List<string> materialKeywordsLst = new List<string>(material.shaderKeywords); List<string> shaderKeywordsLst = new List<string>(); var getKeywordsMethod = typeof(ShaderUtil).GetMethod("GetShaderGlobalKeywords", BindingFlags.Static | BindingFlags.NonPublic); string[] keywords = (string[]) getKeywordsMethod.Invoke(null, new object[] {material.shader}); shaderKeywordsLst.AddRange(keywords); getKeywordsMethod = typeof(ShaderUtil).GetMethod("GetShaderLocalKeywords", BindingFlags.Static | BindingFlags.NonPublic); keywords = (string[]) getKeywordsMethod.Invoke(null, new object[] {material.shader}); …

DLL混淆问题
type: item
date: 2021-11-24T07:17:00+02:00
description: 1）DLL混淆问题 ​2）Unity主程如何做项目管理 3）将ASTC格式转换为png格式 4）iOS 14在iPhone正常，但在iPad上会卡住 这是第276篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Scripting Q：如果不用收费软件和加固，我们自己使用免费软件，如何对DLL进行混淆。 注：之前是用Microsoft.NET/Framework64/v3.5/csc进行打DLL，但是今天我回顾一下发现，DLL并没有混淆。 A1：若在Unity上使用，可以参考开源的方案：Unity Obfuscator Demo 简介 这是一款基于Mono.Cecil库，对C#编译后程序集进行IL代码注入实现的轻量Unity混淆插件，混淆发生在编译后，开发过程无需关心。此插件已在带Lua热更方案的商业MMO手游项目上验证过可行性。 主要功能 对命名空间、类、属性和字段的命名混淆 插入垃圾代码 在原代码中插入对垃圾代码的调用 特色功能 命名混淆支持随机字符串或从词库抽取名字 支持随机种子，可实现重复Build后混淆结果一致 支持黑白名单，排除部分在混淆后不能正常工作的代码，确保项目正常运行 混淆后输出混淆前后的名字对应关系文件 支持多DLL 感谢马三小伙儿@UWA问答社区提供了回答 A2：可以看一下AssetStore上的插件，我之前有个项目也用过： https://assetstore.unity.com/packages/tools/utilities/obfuscator-free-89420 免费版基本上可用： https://assetstore.unity.com/packages/tools/utilities/obfuscator-48919 收费版支持IL2CPP，支持程序集定义文件。 感谢萧小俊@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/61922be9d8413e18eb14a43f Unity Q：Unity主程如何做项目管理？比如资源管理、代码管理和工程管理。可以从多个维度讨论下吗？ A1：资源还是比较简单的，首先按照功能或者需求进行文件夹分类，资源的格式可以写一些AssetPostprocessor的代码来强制转换，整个工程的资源管理自动化。 开发的人员比较多，又对代码质量有一定要求，可以考虑用Git，不要用SVN，主程负责Review所有PR的代码，然后定期进行UT和BVT。 工程管理也可以依赖于Git的Tag和Branch来管理，尽量保证每个版本都是ZBB。 主程要做的事情还是蛮多的，简单写了一下，欢迎大家来讨论。 感谢萧小俊@UWA问答社区提供了回答 A2：身为一个合格的主程，我觉得应该具备以下素质： 1.首先是技术方面，就当独当一面，一马当先。 强大的技术支撑是要具备的，这里其实也可以细分，一个是专业性和广度。先提升某一方面的专业度，同时了解学习新技术，在不同领域的知识要有相对的了解。 2.再之就是管理方面，抓主线，控支流。 应该有好的项目框架。框架是为了更好的迭代和规范项目。一切都是为了开发跟成品服务的。所以不管代码规范，资源管理，甚至是使用习惯，都要遵循简单易用，通俗易懂为原则。比如开发了一个工具，功能非常强大，但是没人会使用它。那意义就大打折扣了。 技术上没有捷径，全靠努力跟积累。管理上需要自己思维上变通，多做尝试。但是有一点我觉得要注意，不能什么都面面俱到，主程是要把控大方向的，不能什么都要干预，适当放手，要培养人，不是带人。这样团队才有创新力，团队成员才会有成就感。而不是个人成就。管理是门大学问，不像技术可以有固定的学习思路。需要自己不断探索，才会有自己的风格和魅力。 感谢廖武兴@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/61947fe3d8413e18eb17e003 Texture Q：.astc类文件如何转换为.png文件，Windows操作系统。 A：ARM提供了压缩ASTC和解压的工具。 对应命令： 压缩：astcenc-sse2.exe -cl origin.png example.astc 6x6 -medium 解压：astcenc-sse2.exe -dh example.astc example.png 可以参考：https://github.com/ARM-software/astc-encoder 感谢范世青@UWA问答社区提供了回答，欢…

TextMeshPro备用字体疑问
type: item
date: 2021-09-29T09:52:00+03:00
description: 1）TextMeshPro备用字体疑问 ​2）iOS的部分语言的float分隔符变成了逗号 3）ASTC格式支持与官方文档不符 4）关于音效背景音乐的音频文件的格式设置请教 5）LightProbe的信息位置 这是第269篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Text Q：TextMeshPro设置的Fallback “字体B”， 文本字体是“字体A”，如果文本显示的字符都是字体A的，CPU会不会收集字体B的贴图信息数据发送给GPU用来渲染？ 不是很理解这个Fallback字体，发现字体A、字体B都在内存中，也就是说其实都是关联上的。是不是所有的后备字体都会在内存中出现？ A：问题一：TMP中所谓Fallback，也就是后备字体，其含义在于当实际使用中出现了当前字体所不支持的字符时，按照：主字体（也就是当前字体）、主字体的后备字体、后备字体的后备字体、通用后备字体、通用后备字体的后备字体、通用默认字体、通用默认字体的后备字体等等的序列遍历所有设置的后备字体，直到找到能够支持的字体为止。 所以，引擎只有在内存中保留Fallback字体资源，才能在当前字体无法显示所有字符时采用Fallback字体。问题中提到的字体B也在内存中是合理的。 当然，如果开发者能确定字体A可以支持项目中出现的所有字体，那么完全可以检查Project Settings中全局的Default Font Asset、全局的Fallback Font Assets List、字体A的Fallback Font Assets，以上三处设置为空，则可以一定程度上节省内存。 问题二：我补充做了实验。对照情况是用某一种主字体显示“New Text”这一串字符，显然足够支持、而内存中也只有该主字体。然后在刚才提到的主字体的后备字体、后备字体的后备字体、通用后备字体、通用后备字体的后备字体、通用默认字体、通用默认字体的后备字体这个序列的每个环节加上不同的字体，显然它们没有被实际用到，但都进入内存了。List里面有几种字体也是一样。 感谢Faust@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/61455c7a8f8c834241ad6caf iOS Q：最近我们打包的时候发现，在iOS设备上，部分语言的小数的分隔符变成了逗号，比如俄罗斯语。后来发现是因为CurrentCulture变成了设备的语言，Android和之前的iOS设备都是en-US，也就导致了读取配置时用float.TryParse会转换失败。 我们的Unity版本是2018.4.33，目前还没有定位是什么原因导致的，不知道有没有人碰到过？如果在游戏启动时强制把CurrentCulture改成英语不知道可不可行？ A：我们项目踩过这个坑，原因就是一些语言里面小数点分隔符不一样，比如法语里分隔符是逗号，属于文化差异。解决方案是游戏启动时设置CurrentCulture为CultureInfo.InvariantCulture： CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; 参考链接：CultureInfo.InvariantCulture 感谢张迪@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/614bf82a8f8c834241b6484d Texture Q：ASTC格式支持与官方文档不符，根据官方文档（https://docs.unity3d.com/Manual/class-TextureImporterOverride.html）。理论上我们的测试机中，红米2是不支持的ASTC格式的。但实际测试中发现，它是支持的。这是怎么一回事？ A：之前做过相关的测试，红米2（Adren 302）是支持ASTC的，但红米Note2（PowerVR Rogue G6200）是不支持…

Lua与C#传参
type: item
date: 2021-07-13T12:27:00+03:00
description: 1）Lua与C#传参 ​2）Unity发布iOS版本出现屏幕问题 3）安卓的View成为Unity界面的一部分 4）Unity升级导致项目启动时间过长 5）Unity中Cascaded Shadows在移动端的设置 这是第258篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Lua Q：游戏中是先在Lua中String.format好再传入C#，还是在Lua里把参数传入C#，在C#里用String.format好？ 即一个是Lua加载文字表，String.format后传给C#显示，另一个是C#读表，Lua把参数传给C#，再string.format使用，哪个方式更好些，或者有没有其他更好的方式？ A1：搬运群里大佬的问答：第二种比较好，因为传参越简单越好，参数可以打包传。 感谢Tao@UWA问答社区提供了回答 A2：可以参考一下这篇文章：《用好Lua+Unity，让性能飞起来——Lua与C#交互篇》，总之Lua与C#传参，优先考虑int、float和double等类型，其次bool、string及object等类型，同时尽可能降低交互次数。 感谢羽飞@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/60e41d96e58b4719dd3e2916 iOS Q：Unity发布iOS版本在iOS 11之后出现屏幕显示问题：半屏被压缩，另一半黑屏。 A：直接在编辑器中设置这几个参数，不要在代码中设置这个，7p就不会出现这个问题： Screen.autorotateToLandscapeLeft = true; Screen.autorotateToLandscapeRight = true; Screen.autorotateToPortrait = false; Screen.autorotateToPortraitUpsideDown = false; Screen.orientation = ScreenOrientation.AutoRotation; 感谢许家胜@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5ab9ef650b827e2c0bfdd1b6 Unity Q：加载了一个安卓的Activity，会遮挡住Unity的界面，如何让安卓的View，成为Unity界面的一部分呢？Unity界面的一部分使用安卓原生SDK的界面实现。 A：安卓混合Unity的界面，已经完成了。 https://blog.csdn.net/Yzw_92_4_11/article/details/68952529 感谢题主韩飞@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/60e6caa7e58b4719dd3e296b Editor Q：查看了Unity的editor.log发现里面： RefreshInfo: InitialScriptRefreshV2(NoUpdateAssetOptions) RefreshProfiler: Total: 0.000ms InvokeBeforeRefreshCallbacks: 1115393.587ms ...... OnSourceAssetsModified: 340.325ms ...... ImportAndPostprocessOutOfDateAssets: 1032441.185ms (82533.117ms without children) ImportManagerImport: 82501.381ms (0.000ms without children) ...... 有没有大佬知道这个是在处理什么东西？科学上网了也没有查到相关信息，这里看耗时就很长时间了1115393.587ms。 A：参考以下几点： 检查一下项目是不是放在机械硬盘上，建议放NVME的固态上。因为高版本的数据结构更复杂了，不用固态来不及序列化。 检查一下是不是开了PlasticSCM。 感谢萧小俊@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/60e2afece58b4719dd3e28ed Rendering Q：Unity的Shadow Cascade功能在移动平台中是否生效？ 在场景使用了Unity自带的实时阴影，具体参数如下： 用Frame…

带多个Submeshes模型合并，显示​异常
type: item
date: 2020-12-30T04:18:00+02:00
description: 1）多个Submeshes模型合并，显示异常 ​2）Addressable如何删除旧资源 3）对NGUI字体错乱的解决方案 4）GLSL link error: L0010 Uniform '_Color' differ on precision 5）iOS键盘上的输入框提示内容如何去掉 这是第233篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Script Q：测试一个Skinmesh合并功能，发现当Mesh包含多个Submeshes时，合并成功后，无法渲染显示出来。当测试的Mesh不包含Submeshes时，可以合并显示。难道CombineMeshes只能合并不带Submeshes的Mesh？ 注：不管是使用r.sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false)；带上所有材质，还是r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false) ；合并一张贴图材质，带多个Submeshes的模型只能合并无法渲染显示出来。不带多个Submeshes的模型却能够正常合并显示。 A：测试发现，需要对每个CombineInstance重新指定三角面，才能正常显示带多个Submeshes的模型。如下代码： foreach (SkinnedMeshRenderer smr in allSkineMeshList) { for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++) { CombineInstance ci = new CombineInstance(); ci.mesh = smr.sharedMesh; ci.mesh.triangles = smr.sharedMesh.triangles; //这里重新指定 ci.subMeshIndex = sub; ci.transform = matrix * smr.transform.localToWorldMatrix; combineInstances.Add(ci); } 感谢题主牛头人不服@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5fe55b1a10a17c6c2b09d778 Addressable Q：目前计划使用Addressable来实现资源热更新，实际真机测试发现当资源更新后，旧的资源Addressable并不会把它删除，同时可以看到App占用的数据文件会越来越大。请问有什么办法可以把指定的Group或Label的资源删除吗？ A：我们用的是覆盖式更新的流程（不是增量更新），Addressables版本是1.15.1。在把Bundle Naming设置为Filename后发现，在Caching中的AssetBundle目录还是带有 Hash值的。 图中可看到AssetBundle包名已经是Group的名字了，但是下载到Caching中还是有Hash。 然后我们是这么解决的：还是开启文件名的Hash，将Caching中的AssetBundle文件夹名保存到PlayerPrefs中，当检测到有下载的时候，读出PlayerPrefs中的值，把旧的对应AssetBundle包删除，并更新PlayerPrefs。 获取当前Catalog中所有AssetBundle文件夹名的方法，是从Addressables中复制出来的。 // 获得当前catalog中所有 assetbundle 保存的文件夹名 // 这个函数中引用到的方法没有列出，可以去 addressables 中源码中找 // 示例：CollectBundleNames(new string[]{ "SkllIcons", "ItemIcons", "AvatarIcons" }) private static List<string> CollectBundleNames(object[] keys) { List<string> result = new List<string>(); #if ENABLE_CACHING foreach(var key in keys) { IList<IResourceLocation> locations; if (key is IResourceLocation resourceLocation && …

Unity Batches与glDrawElements的关系
type: item
date: 2020-10-12T10:06:00+03:00
description: 1）Unity Batches与glDrawElements的关系 ​2）渲染大面积草地时，如何降低消耗 3）HUD随着摄像机偏移 4）Unity中如何在竖屏模式的UI之上显示强制横屏的UI 5）iOS能耗问题 这是第222篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Rendering Q：Unity里用FrameDebug显示DrawCall是422个，Batches是435个，在SnapDragonProfiler里抓取出来glDrawElements数目是1449个，怎么理解这种差异? A1：可参考以下几点： 题主的数据有一点问题，DrawCall数目应该大于等于Batches。根据特定的规则，多个DrawCall可以视为一个Batch，一个Batch中包含多个DrawCall，节省了一部分CPU提交数据的操作。 调用glDrawElements函数进行绘制就是DrawCall的一种形式。 感谢Vest@UWA问答社区提供了回答 A2：这部分可以参考UWA Day 2020里张强老师的分享《Unity移动游戏项目优化案例分析（上）》中的第二小节。 感谢范君UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f33b10e9424416784ef1bdd Rendering Q1：渲染大面积草地时，如何降低消耗？ A1：有以下几点： 使用DrawMeshInstance。 上面这个API是不会进行视距剔除，视锥体剔除和遮挡剔除的。 下面有两种方案： a. 将草地按区域分组，用每组的中心点计算视距，依据距离切换网格LOD或剔除。 还能用向量点乘简单剔除在相机后方的草地。（注意临界问题） b. 借助CullingGroup。 CullingGroup.onStateChanged事件绑定，通过事件触发调整传入DrawMeshInstanced的Matrix顺序和渲染数量。（比较难的是，DrawMeshInstanced只能指定渲染前几个Matrix） 通过cullingGroup.SetBoundingSpheres实现视锥体剔除和遮挡剔除； 通过cullingGroup.SetBoundingDistances实现视距剔除和LOD； 这个方案也最好进行区域分组，不然CullingGroup的事件监听占用会比较高。中端机上4000个监听会占约2ms。 以后如果有对比两种方案的性能，我再进行补充。 附： CullingGroup API的使用说明 Unity 3D研究院之Lightmap支持GPU Instancing 如何高效使用GPU Instancing技术来进行草丛渲染 升级Unity 2018过程中，遇到的DrawMeshInstanced不生效的问题 感谢题主李先生@UWA问答社区提供了回答 A2：可以使用Indirect模式的Instancing，配合ComputerShader实现视锥剔除和遮挡剔除。 感谢邹春毅@UWA问答社区提供了回答 Q2：手机上能用吗？ A：推荐一个使用URP制作的草海效果，亲测可在Mobile端使用。 Unity URP Mobile Draw Mesh Instanced Indirect Example 性能测试： can handle 10 million instances on Samsung Galaxy A70 (GPU = adreno612, not a strong GPU), 50~60fps, performance mainly affected by visible grass count on screen(draw distance = 125) can handle 10 million instances on Lenovo S5 (GPU = adreno506, a weak GPU), 30fps, performance mainly affected by visible grass count on screen(draw distance = 75) 感谢Vest@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5e919a528cabe84a011afcde Rendering Q：HUD为什么会随着摄像机偏移？ 代码如下： Vector3 midVe1 = obj.transform.position; Vector2 …

开发期资源管理的策略选择
type: item
date: 2020-07-20T10:34:00+03:00
description: 1）开发期资源管理的策略选择 ​2）iOS14启动就Crash 3）IL2CPP加密：global-metadata.dat在iOS下的解密问题 4）如何实现可程序控制的3D动作 5）Unity Editor内Screen的Width和Height 这是第212篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间10分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群2：793972859（原群已满员） Resource Q1：因为打包需要用AssetBundle，但是开发中用AssetBundle不太友好，以上两种加载都会有各自的问题： Resources：需要放在Resources文件夹下，打包不好处理。 AssetDatabase：没有异步加载方法，开发中没办法模拟一些需要异步加载的情况。 目前项目用的Resources，打包机分了两个项目，打APK的项目阉割了Resources，写了单独版本管理更新命令，但是依然挺麻烦。大部分公司都是用的AssetDatabase，请问是否有一些方法可以模拟异步加载？ 另外以上两种方法都无法模拟真实的卸载情况，导致组员不合理操作时，打AssetBundle后会有内存泄漏或者丢失引用的情况，可以说一些大家公司开发时用的资源管理方案吗？ A1：用AssetDatabase可以加一些随机延时模拟异步，资源加载的接口可以封装一下，做到根据配置来决定走AssetDatabase还是走AssetBundle。 我们打包机会把打好的AssetBundle自动提交到SVN，可以随时更新下来，在编辑器下测AssetBundle比较方便。 另外：新的Addressable也可以试试看。 感谢littlesome@UWA问答社区提供了回答 A2：听说过一个项目组做法是：平时开发使用Resources来加载；打AssetBundle或者正式包时，按某些规则根据Resources的目录自动生成一个新工程，这样就不用维护两个工程了。 感谢张迪@UWA问答社区提供了回答 A3：之前是协程模拟AssetDatabase下的异步，即LoadFromFileAsync。 后面尝试过一种方法，就是使用单独的美术工程处理AssetBundle，然后程序工程不负责任何资源，只使用美术工程打包生成的AssetBundle。初听上去流程比较复杂，一点点小的改动即需要操作2个Unity工程。但是其优点也是非常多的。 代码上可以保留AssetDatabase的加载部分用于调试，当然能在日常开发中使用AssetBundle大部分时候能把AssetBundle的Bug暴露在Editor端，而不是上了真机才出问题。 感谢cloud@UWA问答社区提供了回答 A4：以前是用Resources来加载，只不过会把资源放到Editor/Resources目录下来避免被打进包内。 然后要发布的时候切换Flag，并读取Editor/Resources目录下资源进行打AssetBundle包。不过现在全部交给Addressables来管理了。 感谢黄程@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f0acbca39b05c2c143aa37e iOS Q：在iOS 14发布之后，就出现闪退问题了。和机型没关，只要是iOS 14就必闪退的那种，iOS 13就正常。用的Unity版本是2018.2.3。请教有人遇到过吗？ A：我们iOS14也出了状况，有两个表现： 启动就闪退，多起几次可以过去。 启动后到某个阶段之间卡死（必卡跳不过）。 XCode里看，始终是GfxDriver报错，我们渠道方发现，XCode里【BuildSetting - Packaging - Product Name】不能含有中文，有中文就出这个问题，改掉就好了。 根本原因尚不明确，个人猜测Product Name会影响Header Folder Path，可能是代码加载路径中出现中文会出问题（类似早期Unity的状况）。希望对你有帮助。 感谢Walker@UWA问答社区提供了回答，欢迎大家转至社区交流： https://answer.uwa4d.com/question/5f0c6d02423c965a6f40736c iOS Q1：为了加大破解难度，需要对global-metadata.dat文件进行加密。 实现方式是： 1. 加密在导出Android和Xcode工程后进行，对global-metadata.dat按字节加密。 2. 修改： Android：\Editor\Data\il2cpp\libil2cpp\vm\Met…