技术分享连载(七十三)

技术分享连载(七十三)

本期我们聚集了这些话题:界面的快速隐藏和显示、AssetBundle加载失败、UGUI性能剖析、获取物体的最小Collider包围盒...


我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
UWA QQ群:793972859
UWA 问答社区:answer.uwa4d.com


UI

Q1:众所周知,UGUI中有个Canvas.sendWillRender()函数在View打开的时候很耗时,所以通常的做法是把View移出屏幕外,或者Canvas.group,或者Scale等类似的处理机制。这样虽然能解决SendWillRender()消耗过高的问题,但也会有新的问题出现:

1. EventSystem.Update()。由于各个View都是Active的状态,所以这个函数底下的Graphic.GetDepth()消耗很大,而且又由于不止一个GraphicRaycaster组件,所以这个函数下面的List.Sort()消耗巨大,更何况是每帧都在耗。

2. 还有一个函数ScrollRect.LateUpdate(),它的开销也很高。而如果将Scale设置成0,其消耗更大,这种情况下,我还是倾向于用回Active/Deactive的处理机制,因为就界面打开的时候会卡一下,而不至于影响总体的帧率。

对于以上两点,不知UWA有什么建议吗?

界面的快速隐藏和显示,比较推荐的做法是:

  • 把界面单独作为一个Canvas,并绑定一个相机,同时在绑定相机的Culling Mask中设置一个不渲染的Layer;

  • 隐藏时,把Canvas移出相机范围,同时把Canvas的Layer改为不被渲染的Layer,禁用对应的GraphicRaycaster组件,把Canvas中所有的动态UI元素停止。

  • 显示时,移回Canvas,改回Layer,激活GraphicRaycaster组件。

针对题主的问题1,禁用GraphicRaycaster组件后就没问题了,被禁用的GraphicRaycaster不会进行Raycast操作;

针对题主的问题2,ScrollRect.LateUpdate中会通过EnsureLayoutHasRebuilt提前触发Canvas.SendWillRenderCanvases(),所以实际上还是Canvas.SendWillRenderCanvases()的开销。Canvas.SendWillRenderCanvases()开销高,是因为用Scale改为0的方式会清除顶点信息,在Scale改回1的时候还是需要重新创建顶点信息,开销肯定还是很高的,所以不推荐用Scale改为0来隐藏复杂的UI界面。

此问答来自于UWA 问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59782a4ddb9f756873790717


资源管理

Q2:我们是Unity 4.x项目,现在会出现The unity3d file is not a valid asset bundle,www.error为空的报错,请问是什么原因导致的呢?

如果这个Log是随即出现的,那么需要检测一下AssetBundle使用代码。该Log是指通过所需要加载资源的AssetBundle并不是有效的AssetBundle文件,那么出现这种情况主要有以下几种:

  • 确实不是AssetBundle文件;

  • AssetBundle还没有加载完就开始使用;

对于题主遇到的随机现象,很可能是第二种。对此,需要题主在AssetBundle使用时确保其www.isDone为true。同时,在Unity 4.x版本中,尽可能确保大量AssetBundle加载时,New WWW加载和Unload操作是分开操作,不要耦合在一起。

此问答来自于UWA 问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/597b3c2c58c8409c0dc7e2cb


动画

Q3:我使用相同的角色FBX,一个使用Optimize GameObject, 一个不使用。

请输入图片描述

在此基础上创建各自的Prefab,播放相同的Idle,观察sk_palm_l,一个如下图:

请输入图片描述

另一个如下图,可以发现朝向不一致,请问这是什么原因?

请输入图片描述

先来看原因。对于Humanoid来说,Skeleton信息会被映射到Mecanim internal skeleton中。在Optimize之后,Scene中已经没有了骨骼Hierarchy的信息,所有骨骼的更新将直接使用Mecanim internal skeleton计算。因此,在Optimize之后,决定骨骼朝向的是映射到Mecanim internal skeleton中的朝向信息。

然后,这个信息其实在Configure Avatar时可以看到:

请输入图片描述
图中可以看到,其实映射时Rotation已经归零了,所以Optimize之后的朝向其实是Rotation相对父节点为0时的朝向。

我们建议题主可以做以下尝试: 该界面里有个Pose->reset,这样该transform就会恢复,然后再enforce T其他配置就好了。或者手动修改这里的transform。

另外补充两点:

  • Pose->Biped Pose会把所有不带动画且不在muscle中的骨骼的rotation归零,所以要重置一下。
  • Generic不存在映射,所以始终一致。

此问答来自于UWA 问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59748dce279536386cc41cee


动画

Q4:我在使用Ragroll时,自动生成的Collider的位置会出现错误,Pelvis和MiddleSpine分别在左右胸上,如下图所示。这是为什么呢?

请输入图片描述

UWA试验了题主提供的FBX,确实存在所述问题。其中,我们发现模型骨骼Hierarchy与Unity推荐的Hierarchy有出入(注意Spine和Pelvis),可能是这个原因导致。在其它骨骼层级一致的模型上实验是正常的。 题主可以修改模型骨骼层级后再导入试下,或者在Unity中手动修正下Collider。

此问答来自于UWA 问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5972e8c08b984ede53d94121


物理

Q5:我想了解下如何获取物体的最小包围盒?Collider.bounds.size 获取的是与世界坐标系坐标轴平行的包围盒(AABB),当物体旋转时包围盒大小会发生变化。那如何获取物体的OBB,使包围盒的大小不会随物体旋转而改变呢?

获取 OBB 可以用 Mesh.bonuds(模型空间)。注意蒙皮Mesh这一类在Shader中修改顶点坐标的操作。

此问答来自于UWA 问答社区,感谢 jim 的回答。该问题已被解决,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/597a9419ca8ea5ac0a599067


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