关于UniRx的使用心得分享

关于UniRx的使用心得分享

这是第139篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。UWA 问答社区:answer.uwa4d.com,UWA QQ群2:793972859(原群已满员)。

本期目录:

  • 关于UniRx的使用心得分享
  • 特效是否值得做贴图合并优化
  • AssetBundle LZMA,LZ4压缩
  • Unity 5.6.5 iOS渲染相关的闪退问题
  • Shadows.RenderShadowMap的耗时优化

逻辑代码

Q:求在正式项目中使用过UniRx的朋友聊聊使用感受,之前有偶尔看到过一些UniRx的文档,前段时间翻QFramework的时候又看到在推荐这个东西,今天翻开源库的时候也看到它的热度在很靠前的位置:UWA开源库:UniRx

于是仔细读了一下文档,挺有兴趣的,想在新的公司框架内加入这套东西,但是又没有在正式项目里用过,不知道是否会有一些内存、使用等方面的坑。

“UniRx (Reactive Extensions for Unity) is a reimplementation of the .NET Reactive Extensions. The Official Rx implementation is great but doesn’t work on Unity and has issues with iOS IL2CPP compatibility. This library fixes those issues and adds some specific utilities for Unity. Supported platforms are PC/Mac/Android/iOS/WebGL/WindowsStore/etc and the library.”

从设计理念上来说,基于Event(Action)的思路来解决异步编程的问题,同时弥补Unity协程里的一些小不足,看上去比较美好,然而它们依然是基于轮询或者已有事件的封装,担心后续的维护成本的增加以及如果真的有性能问题需要优化的代价,所以先问问社区的朋友,有没有在项目中大范围应用的,求分享下实际使用中的优势和坑~
Assets Store上的评价也都比较高...

目前项目中小范围使用过一段时间,但由于一些原因又替换掉了,仅谈谈个人看法,如果有错误还请轻喷。

1)熟悉上手需要一段时间,对于团队整体素质有一定要求,如果对这个东西不是特别熟悉的话,有可能写出比较恶心的代码。
2)执行顺序不太可控,尤其是一些对执行顺序要求比较高的需求,可能会出现一定的问题。并且调试起来不是很直观,代码维护起来比较吃力。
3)性能方面由于只是项目初期小范围使用,所以并没有系统性的测试。

感谢范君@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bf6735f7206a021a29256a4


渲染

Q:我们游戏特效制作方法是一个材质对应一张贴图,都是以散列的小贴图存在的,这样就出现特效DrawCall过高的问题。为了优化特效,能否参考UI图集的思路,把一整套特效使用的贴图打到一个图集中呢?
好处:能有效降低DrawCall;弊端:
1) 公用的贴图要么多次被合并到大图中,要么就要出现公用图集,一个特效需要多张较大贴图的可能;
2) 贴图合并势必会造成包体增大,内存、显存比原先占用更大的情况,不知道会不会造成负优化;

参考两个腾讯游戏,发现他们特效贴图好像是散列的,并没有做合并。想问问各位项目对于特效DrawCall是如何优化的,有没有做过类似的优化或者有更好的优化思路。感谢!

A1:个人认为,特效贴图合并的价值是有的,但是理想的合并方式难度比较高。原因就是在于特效的贴图公用性比较强,而聚集性差。比如UI中的贴图,可以区分共用和专有的两种,大量共用的进行合并,各个系统界面内部的可以合并,这样逻辑上本身具有聚合性。

特效的贴图组织结构通常是按照效果来区分,比如下图所示的文件夹区分方式:
请输入图片描述

按照这种文件夹的方式进行合并,比如把Bloom效果的合并到一起,但是比如一个技能特效带有烟雾,又带有火光,那必然使用了两个文件夹下的贴图,而且DrawCall也不好降低。针对于单独特效进行合并的问题就是题主所说的劣势了,冗余度高,无法照顾全局。这也是题主目前看到大部分游戏针对特效贴图进行合并较少的原因。

我们的做法是默认散列,对于长时间存在、DrawCall影响较大的特效才进行特定针对性的优化(使用专门的图集、控制高低配显示粒子等),通常的特效不做合并处理。

感谢贾伟昊@UWA问答社区提供了回答

UWA:游戏特效中的Draw Call如果研发时间允许,还是建议合批,特别是针对出现频率大致相同的特效。对于粒子系统,建议考虑Texture Sheet Animation功能,这个我们在今年的UWA Day上有详细讲过,题主可以通过Google查一下它的使用方法即可。
请输入图片描述

但是,需要说明的是,在复杂情况下(比如Moba中的团战),依然不可避免地会出现特效穿插重叠等现象,这种情况下很可能依然会拉高Draw Call的占用。所以,只能说上述方法是从概率上降低了Draw Call的使用,具体能降低多少,还需要研发团队根据自己的项目情况自行查看了。
该回答由UWA提供

该问答来自UWA问答社区,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bfcee208cf34950e06a6693


闪退

Q:我用iPhone X在外网上真机测试会发生闪退,具体的表现大概是:游戏突然卡住不,有时会黑屏,过一会就自动退出。闪退后立即刷新Bugly,闪退次数会+1,而且闪退时间吻合。

世界Boss打着打着就闪退了,各种机型都闪,但内网无法复现,外网也已经关闭了,现在不复现根本无法排查问题。看上去似乎是GPU渲染相关的闪退,但因为内网不能复现,无法验证是否解决了Bug。大家有没有遇到这个问题?怎么解决的呢?

具体情况是:
Unity 5.6.5
XCode10.x
iPhone 7Plus、iPhone X、iPhone XS Max都会闪退
我尝试过以下做法:
1)升级Unity 5.6.6,外网还是闪退
2)检查过Unity的设置,是用OpenGLES 2.0渲染的

我的疑问是:我们已经设置了不用Metal渲染,但为什么还能走到AppleMetalGLRenderer这个看似是Metal渲染的接口呢?

题主:经过大量的排查验证,我终于找到了原因(由于过程较为波折不在这里赘述,感兴趣的朋友可以看原贴):
用command buffer渲染阴影时,需要获取所要渲染的Mesh。换装后,会重新CombineMesh。CombineMesh的这一帧,Mesh处于一个“中间态”(可能是Unity的一个bug),当帧用command buffer渲染出来的阴影也是一个不规则的形状,而且XCode会个报错,还可能导致闪退。

解决办法:CombineMesh这一帧不再渲染它的阴影,等下一帧Mesh准备好再去渲染。这样就不会出现阴影的不规则形状,XCode也不会报错和闪退了。

感谢仇磊@UWA问答社区分享了该问题并提供了总结,也感谢UWA群友:贾伟昊、蒙占志、赵林等提供的热情帮助,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bfe4964a5945f12c6d68416


资源管理

Q:我想了解下,既然Unity在下载LZMA文件的过程中就将文件以LZ4的流式存储在缓存中,那是不是可以在下载LZMA格式的文件后存储文件时换成LZ4的AssetBundle包压缩格式存储到本地呢?
请输入图片描述

A:下载LZMA格式的文件后存储文件时换成LZ4的AssetBundle包压缩格式存储到本地,这个想法倒是挺清新的,以前从没想过要这么干。

但是如果从LZMA转到LZ4,一来应该是没有直接转的接口(我是没有见过),二来要经过一个LZMA解压然后再压缩到LZ4,LZMA压缩率很高,解压时间成本就有点高了,况且再加个压缩过程呢?所以我觉得这个方案大概率存在转换时间成本过高的问题,题主还要做评估看是否实现了然后根据测试数据来评估方案,测试数据最有说服力。

常见的做法是一种是直接用LZ4,不再处理或者再压缩下,一种是非压缩的格式然后采用类似7zip等工具进行压缩,至于压缩率自己选,高压缩率甚至可以比LZMA小,当然有代价,压缩率越高,解压时间越长,我们目前采用的是非压缩,压缩工具直接压缩,觉得解压时间有点长,所以可能在压缩率上做平衡或者换LZ4。

感谢赵林@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bfe613d0ed0fd12c17fdf8c


渲染

Q:代码堆栈中的Shadows.RenderShadowMap的耗时比较高,怎么优化呢?
请输入图片描述

UWA:使用实时阴影时,投射阴影的物体会进行一次额外的渲染,而接受阴影的物体也会增加采样阴影强度的计算,所以对渲染耗时的影响比较高。题主这个耗时占比还是比较高的,可以考虑手动控制场景中投射/接收阴影的物体的数量。如果只有角色需要有阴影,可以考虑使用Projector配合FastShadowReceiver。
该回答由UWA提供

A2:两个传送门:
https://blog.uwa4d.com/archives/USparkle_Shadow_effect.html
https://blog.uwa4d.com/archives/sparkle_shadow.html

实时投影的消耗还是比较高的,能做的一般也就是降低阴影质量,控制投射和接收阴影数量等来降低消耗。

我们采用的方案是角色用FastShadowReceiver,静态物体就烘焙,其他动态物体看具体情况,底下给个从中心到边缘模糊的等跟着物体移动或者FastShowReceiver,有些直接就不给投影。
感谢赵林@UWA问答社区提供了回答

该问答来自UWA问答社区,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c0107e63f6fed22e42db636

今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(原群已满员)