这是第113篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。
加载
Q:在使用异步接口 yield return AssetBundle.ASyncLoad的时候,难免会想到:这个异步处理完之前如何取消掉这个任务?也就是一个AssetBundle加载到一半,现在要放弃加载,应该怎么处理?
A1:Unity的接口里没有中断操作,但是可以在自己项目的AssetBundle Mgr模块给业务逻辑层提供一个可中断的接口。也就是Mgr里加载好资源后,如果业务层不需要了,则不返回/不执行回调。至于这个“不需要”的资源是要缓存,还是卸载就得根据自己项目来处理了。
感谢Walker@UWA问答社区提供了回答。
A2:分享一个小的Unity文档上的坑吧,其实我也不知道答案,可能希望有源码的朋友帮忙看看。
在异步请求一个AssetBundle的时候,会返回一个AssetBundleCreateRequest对象,Unity的官方文档上写AssetBundleCreateRequest.assetBundle的时候这样说:
“
Description
Asset object being loaded (Read Only).
Note that accessing asset before isDone is true willstallthe loading process.
”
用了Stall这样一个词,我们之前理解Stall是停止的意思,以为这个接口的调用可以将异步请求打断,所以借助这个特性应用在“同一个AssetBundle正在被异步加载的过程中来了一个同步请求”这样的情况下。
今天看到这个问题,又读了读这个文档,感觉Stall这个词并不是停止的意思,而更可能是“拖延”的意思。如果是一个异步加载请求,那么是在另外的线程里执行的,这时候如果有主线程的访问请求的话,应该会有跨线程的加锁逻辑,从而可能导致加载变得更慢。如果是停止的话,我觉得文档应该使用Stop这样更加明确的单词。
当然这个是我个人的猜测,如果有其他朋友知道准确的意思也烦请告知~
感谢贾伟昊@UWA问答社区提供了回答。
A3:题主碰到的问题和我一样呢, 最后我们是使用Promise方式封装了资源加载的接口。
返回的handle对象状态一旦凝固就不会再改变。
感谢silekey@UWA问答社区提供了回答。
A4:看到贾伟昊说到的这个问题,很激动地去看了一下API和UnityReferenceSource。由于项目一直在用Unity 5.6版本,Unity 2017和2018的AssetBundle这块还没测试过。Unity 5.6是肯定不能取消或者block获取到AssetBundle资源的,看新的Doc里面都提到了能block获取到资源,referenceSource中AssetBundle的API也提到了,Asset的API中没有提到。我的理解应该是在异步没有完成之前,访问资源可以变成同步马上获取到该资源,有测试过的同学可以回答一下。如果真是这样,那就太好了,相信很多项目的设计上都是同步与异步并存的,只是绕过了同步加载一个正在异步加载资源的问题。Unity如果这块修改了,就可以完美解决同步加载一个正在异步加载资源的问题了。
鉴于Unity Doc被坑过几次,更相信ReferenceSource里的,猜测AssetBundle也许实现了同步访问正在异步加载的资源,Asset没有实现。
感谢lichun@UWA问答社区提供了回答。
欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5af3db530e95a527a7a81d31
动画系统
Q:我们跟美术讨论了下想试用70根骨骼(很多预留的飘带)去做角色的动作,但是每个模型(每套时装)只使用其中的30-40根(只做2-3根飘带)参与蒙皮,这样的情况与用40根骨骼去做角色动作(开启了Optimize GameObject后),性能区别会很大吗?
之所以有这个想法,是因为我们想给时装预留更多的发挥空间,一开始我是打算把所有飘带都用代码去控制成动态骨骼,但是在开启了Optimize GameObject后,无法取修改蒙皮骨骼的信息,请问这块有没办法呢?
UWA:第一个问题,即两个情况的性能差异对比是比较难预估的,因为Optimize GameObject是否开启,其实重点影响的性能开销是下图中的DirtySceneObjects和WriteJob一项,而骨骼数量的多少其实是影响下图中的ProcessAnimationsJob一项,所以这两者其实并没有很大的相关性。因此,还是建议题主在真机上对自己的模型进行有针对性测试之后,才能决定这么做是否合适。
对于题主的第二个问题,一般来说,飘带其实可以作为额外的动画文件来进行处理,只要在Optimize GameObject时,将飘带在角色上挂载的父节点暴露出来即可,这样飘带可以走自己的动画计算,并不需要与原来角色耦合在一起。当然,以上仅是一种常规做法,真正适合题主的还需要根据自己项目情况而定。
该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b07d22b09749726e4188d0a
逻辑代码
Q:开发过程中,我们代码给策划美术使用,将C#代码打包成dll文件,性能分析的时候需要使用Profiler打点定位,但在dll里添加打点后,在Unity Profiler面板上面看到不数据。
UWA:在打dll的工程里需要加一个宏:ENABLE_PROFILE
该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b08141654646026e9ddd655
渲染
Q:请问下updateWhenOffscreen有何用,建议开启吗?我们的头发用的是alpha blending的Shader,有时候头发会莫名奇妙消失,我们怀疑是不是这个原因导致。
A:主要是Bounds:
https://docs.unity3d.com/ScriptReference/SkinnedMeshRenderer-localBounds.html
勾上的话,每一帧会更新Bounds。但是看updateWhenOffscreen本身的文档,又感觉莫名其妙。
https://docs.unity3d.com/ScriptReference/SkinnedMeshRenderer-updateWhenOffscreen.html
实测下来勾上的话不离屏也会每一帧更新Bounds,不勾上的话在屏幕上也不更新,而且也并没有发现禁用updateWhenOffscreen会禁用animations。自然是建议不开启的,开启必然有额外的消耗。
你这个问题看起来确实跟Bounds有关系,建议RecalculateBounds预处理一下。
感谢凯奥斯@UWA问答社区提供了回答,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b07485209749726e4188cfe
内存管理
Q:我从性能简报里的【Mono详细堆内存分配】报告中看到第一个ZOutputSteam.ctor 分配了50MB,这部分该如何优化?但从【代码效率/堆内存分配】里又看不到这个。
UWA:ZOutputSteam.ctor说明是ZOutputSteam类在执行构造函数,也就是代码在大量地执行New ZOutputSteam操作来,题主可以看看是否如此,如果是这样,可以考虑采样复用ZOutputSteam的实例,而非频繁的New。
【代码效率/堆内存分配】看到的信息仅是整体的堆内存统计分配信息,所以才需要进行Mono详细堆内存检测。
该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5afebe1b6b104d27ac3aadb6
领取专属 10元无门槛券
私享最新 技术干货