1)本地资源检测,特效检测中 Overdraw 相干问题
2)Android 上如何减速断定 Bundle 文件是否存在
3)xLua pcall 异样捕捉
4)Mipmap 和带宽
5)Timeline 卡顿重大时,Clip 被齐全跳过没有执行
这是第 230 篇 UWA 技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫 10 分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.com
UWA QQ 群 2:793972859(原群已满员)
Rendering
Q:咱们这个特效资源检测 Overdraw 和理论检测差距有点大。是不是统计峰值比拟好一些?有可能一个特效播放工夫特地长,然而峰值就很短的工夫,这样一均匀 Overdraw 就很低了。
A:首先要谈谈 Overdraw 的定义问题:
- Overdraw 是一个形容像素反复绘制次数的概念。单个像素的反复绘制次数很容易了解,然而对于一个特效的 Overdraw,笔者还没有找到什么公认的“规范”的计算公式,也不存在什么“官网”的定义。
对于一帧来说,Overdraw 值能够定义为该帧总体绘制像素的次数 / 屏幕上理论绘制的像素数。而这个值也不能简略了解为“绘制的层数”。(试想如果总共在屏幕上绘制了 1000 个像素,其中只有一个像素绘制了 10 层,那这个反复绘制的像素对 Overdraw 值得奉献也是能够疏忽的,计算结果为:1009/1000=1.009)。而对于整个特效播放过程中的 Overdraw,具体公式如何定义,又是一个问题。
- sunbrando 的开源库的计算方法:整个播放过程中,
分子是 对每一帧绘制像素的次数求和 ,分母是对 每一帧屏幕上理论显示的像素数求和。
这个公式的确能够从整体上掂量一个特效播放过程中的 Overdraw。然而这种计算存在这样一个问题:有些帧特效占屏幕的比例很大,有些帧特效占屏幕的比例很小,而运算后果受屏幕占比大的帧影响比拟大。比方第一帧绘制了 1000 个像素,只绘制了 1 层,而第二帧绘制了 2 个像素,绘制了 10 层,那么计算出的值为:(1000×1 + 2×10) / (1000 + 2) = 1.018。
UWA 本地资源检测对特效 Overdraw 的计算与上述开源库计算公式是雷同的,不同的是特效播放的逻辑与相机对准的形式。
影响两个工具计算结果不同的因素有:
- 相机的对准形式不同。UWA 的工具有一套相机主动对准的逻辑,相机的摆放不同,会造成 Overdraw 不同。
- 播放的机会不同。UWA 的工具会创立好场景后,主动加载并实例化特效,进行播放。而开源库 ParticleEffectProfiler 的计划是先把特效放到场景中,启动场景后再执行相干的逻辑,进行检测。
楼主的案例中,除了相机对准形式不同导致两个工具计算结果不同之外,很大水平上受到了获取的特效播放机会的影响。
应用开源库工具进行检测,发现抓取相机的 Overdraw 数据前,曾经进行了三次 Update,如下图所示。也就是说,特效的 Overdraw 是从第 4 帧开始统计的。这与该工具的代码逻辑无关,就不对起因进行剖析了。
而前三帧恰好又是在数值上奉献最大的帧,如下图所示,前三帧特效中有一个面片占了很大的屏幕空间。
而第四帧开始,特效的像素占比就小了很多。
这是两个工具即便应用雷同的对准形式,Overdraw 计算结果也不雷同的起因。
另外,UWA 的特效检测还存在一个问题:相机视锥体的 Size 是一直调整的,那么不同的帧特效的屏幕占比会因而而扭转,像素的绘制量也不同,对上述 Overdraw 值计算公式的奉献也就不一样。也就是说,相机的 Size 越小的帧,特效屏幕占比越大,对后果的影响越大。
这里有两套解决方案:
- 换公式,每帧都计算出 OverdrawRate,再求均匀。
- 用户自定义相机,相机的视锥体放弃固定,这样就是放弃主动对准,使相机的设置更靠近用户的理论应用环境。
UWA 的工具会一直迭代,依据需要尽可能找到一套最佳策略来帮忙开发者对我的项目进行标准。
如果在优化中要应用工具进行检测,并掂量优化的后果,倡议应用一套工具即可。应用同一套规范至多能够对资源的性能进行一个排名,据此来抉择优化的优先级,并应用同一套规范评估优化后果。
感激 Prin@UWA 问答社区提供了答复
AssetBundle
Q:咱们在 Android 平台上打包时,把 Bundle 放到 Streaming Assets 中,Patch 文件放到长久化目录中。在启动时判断:Patch 目录有 Bundle 就用 Patch 目录的,没有就看 Streaming Assets 目录有没有。
问题是:Android 判断 Streaming Assets 下是否有文件,要用 www 或 UnityWebRequest。这两种都是异步读文件,期待异步操作完结须要几毫秒以上,导致判断逻辑耗时很长(Bundle 较多)。
想求教下大家是怎么解决 Android 上的文件断定问题呢?
A1:Streaming 里放个资源字典文件,用这个判断。
感激 lanyt@UWA 问答社区提供了答复
A2:能够这样来解决:
有一个全局的 Bundle 资源的配置文件,外面记录了所有 Bundle 的信息,这外面会蕴含其相对路径。只有从包外面读这个文件是须要异步的,如果从 Patch 目录读这个文件也是同步的(例如应用 FileStream)。
失去了所有 Bundle 的相对路径后,在理论须要加载某 Bundle 时,先应用 File.Exist 或者直接判断 AssetBundle.LoadFromFile 的返回值是否为 null 来判断 Patch 目录是否有该 Bundle,如果没有的话再应用包内门路从新调用 AssetBundle.LoadFromFile 即可。
经测无效,把文件判断扩散开,Patch 目录能够间接用 File,不存在就认为是在 Streaming Assets 目录,最初利用 Load 的后果来更新,看是否存在的记录。
感激范君 @UWA 问答社区提供了答复
A3:有一个不错的开源库,可能同步读取 StreamingAssets 下的文件:
《BetterStreamingAssets》
感激张迪 @UWA 问答社区提供了答复
LUA
Q:想请问下在 xLua 中应用 pcall/xpcall 实现 C# 中的 Try Catch 性能的时候,在 iOS/Android/ 模拟器等平台上,有什么须要留神的中央。
因为对 Lua 底层不是很理解,想确认下,线上我的项目应用是否可行。还有这个的性能耗费有多少,Update 里能够用吗?
我的项目应用的是 xLua,版本是 2.1.14,Unity 版本是 2019.4。
A:大范畴的应用中,pcall 和 xpcall 自身必定有肯定的性能影响,不过咱们倒是没有做过很齐备的性能测试比照。印象中之前做过一些检索,没有找到特地明确的答案。
Lua 中源码的实现比照能够参考这里:
https://stackoverflow.com/questions/16642073/whats-the-difference-behind-normal-function-call-and-pcall/16642612
能够看到 pcall 确实比惯例的 call 多做了一些事件,只是这是 Lua 做异样捕捉的惟一形式,当你不想游戏逻辑被错误信息打断的时候,只能应用它。
pcall/xpcall 在各种平台和模拟器上除了稍微的性能影响之外没有任何问题,因为它是 Lua 原生的形式,如果应用 LuaJIT,留神一下 Lua 和 LuaJIT 下的区别封装即可。
感激贾伟昊 @UWA 问答社区提供了答复
Rendering
Q1:请问,Mipmap 到底能不能升高带宽,如果不能升高,是否具体通知一下起因,谢谢。
A1:能够升高!
Mipmap 是为了解决 Texel 和 Pixel 没有 1:1 对应的一种解决形式。一般来说如果解决远处物体的渲染,仍然应用失常的纹理采样,那么其实 1 个 Pixel 就个别须要采样到多个不相邻的 Texel[1:n 的关系],那么不相邻这就可能波及到一个 Cache Miss 的问题。而 Cache Miss 必然须要从显存中从新采样纹理数据,这天然就会耗费带宽。
感激会丢锅的 Coder@UWA 问答社区提供了答复
A2:是能够升高带宽开销的。
次要是因为在渲染相邻 Pixel 的时候,采样的 Texel 可能是在内存中不间断的,而 GPU 的 Texture Cache 是很小的。
如果没有 Mipmap,在渲染远处物体时,GPU 可能须要不停的在贮存 Texture 的各段 Memory 不停的拜访,Cache Miss 很重大。而应用了 Mipmap 后,相当于离线将每个 Texel 笼罩的 Texture 的面积变大,这样能够晋升 Texture Cache 的命中率,从而缩小间接从内存读取数据的次数,从而节俭了带宽的开销。
感激范君 @UWA 问答社区提供了答复
Q2:请问上文中:
1.“而应用了 Mipmap 后,相当于离线将每个 Texel 笼罩的 Texture 的面积变大”,这里是 Pixel 还是 Texel?
2. 还有就是 Memeory 是指内存是吧?不是曾经把一张图提交给了 GPU 显存了吗?
A:能够看下我知乎的这个答复,解决你对 Pixel 和 Texel 的纳闷:
《shader 中,fwidth 或者说 ddx/ddy 到底是什么意思?》
感激止戈 @UWA 问答社区提供了答复
Timeline
Q:Timeline,如果在播放时卡顿重大,会呈现后面地位的 Clip 被齐全跳过没有执行,有没有人碰到过相似的问题?
Timeline 信号的这个形容,是不是即便信号跳过了,依旧会执行?
The Retroactive property, when enabled, will trigger the signal if the timeline begins playing after the signal’s time.
The Emit Once property, when enabled, will trigger the signal only once when the timeline loops.
A:勾上之后是会执行,具体逻辑可参考 TimeNotificationBehaviour 脚本(Timeline 中 Signal Track 的 mixer 逻辑脚本),如下做了简略正文:
如果须要倒放也会 Trigger,也能够参考这个扩大本人的 Timeline。
感激羽飞 @UWA 问答社区提供了答复
封面图起源:Barracuda Style Transfer code sample
明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在 UWA 问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA 学堂:edu.uwa4d.com
官网技术 QQ 群:793972859(原群已满员)