Unity中UI、3D和特效的层级管理方案
Unity中UI、3D和特效的层级管理方案
在Unity开发中,UI、3D模型和特效之间的层级管理是一个常见的问题。本文将详细介绍几种解决方案,包括使用RenderTexture、骨骼动画组件替换、以及通过Sorting Order进行层级控制等方法。
使用RenderTexture
在某些场景下,如果只有很少的3D模型(只要带MeshRenderer组件),可以将相关的模型的layer设置为一个专门的layer,然后使用一个摄像机来对它们进行绘制。并将绘制的结果输出到一个RenderTexture上,最后将这个RenderTexure设置到某个RawImage上。这样,即所谓3D转2D,将3D的物体变为2D的图片。这样的图片和其它的图片一样的用法,不会产生层级和点击的问题。
注意,摄像机的ClearFlags要选择"Depth Only","CullingMask"选择那个专门的layer。
骨骼动画使用SeletonGraphic
如果是在UI场景中使用的骨骼动画,比如大厅等界面。因为默认情况下骨骼动画使用Skeleton Animation,而该组件使用的是Mesh Render组件来渲染,会与UI产生层级问题。我们可以使用SeletonGraphic组件来替换Skeleton Animation,按照2D的模式来播放动画。这时,动画相当于是一个2D动画,就不会有层级和点击的问题了。
将Mesh相关的三个组件去掉:Skeleton Mesh, Mesh Renderer, Skeleton Animation,然后添加Skeleton Graphic,添加骨骼数据文件和材质。
通过设置Sorting Order
Canvas使用Canvas Renderer来渲染,在所有的renderer绘制完毕之后再进行UI元素的绘制,所以一般UI元素会显示在所有物体的最上层。我们可以通过设置Canvas的的渲染模式来改变这一逻辑,即RenderMode设置为Screen Space-Camera来将Canvas当做普通的Renderer来渲染。默认是Screen Space-Overlay,也就是显示在最上面。
这样,一个Canvas所包含的UI元素就和普通的3D物体一样,可以通过设置Canvas或者3D元素的Renderer的sortingOrder来进行手动层级控制。
修改Canvas的Sorting Order
将根Canvas的渲染模式设置为Screen Space-Camera,选择一个SortingLayer,比如Default,然后设置一个基础Order,如1500。
然后将每一个单独的预制(代表一个窗口)都挂上单独的Canvas,勾选Override Sorting,然后选择与根Canvas相同的SortingLayer,之后指定一个基础Order。每个窗口层级都预留一些Order空间给其子节点使用,如第一个Window使用1600,第二个Window1700,之间差的100就是给窗口的子节点使用。
这里要注意,为了使UI元素获得点击等事件,需要额外添加Graphic Raycaster组件。
修改3D元素或者特效的层级
3D元素和骨骼动画一般使用MeshRenderer组件,粒子特效一般使用Renderer组件。在MeshRenderer组件中没有找到SortingLayer和OrderInLayer属性,因为其继承于Renderer,属性被隐藏,但是可以通过代码来设置。网上有很多组件可以用来设置MeshRenderer的Order,大家可以选择使用。
通用解决方案
通过手动(代码管理)调整Renderer的渲染Order来处理UI、3D、特效之间的层次关系。我们可以制作一个组件,这个组件可以将一个节点的所有子孙节点的SortingOrder设置为与自身保持一致。如果子节点有Canvas组件,则设置其Canvas组件的Order,如果子节点有Renderer组件,则设置其Renderer组件的Order。其他子节点默认保持和父节点一样的Order,不需要主动设置。
这时,所有的子节点都与父节点有一样的Order,默认根据其Hierarchy顺序来绘制。在某些需要特殊处理的节点,比如3D元素或者特效要显示在某些UI元素之下或者夹在元素之间的需求时,我们可以单独控制涉及到的子节点。
比如我们需要将一个骨骼动画显示在两个图片之间,我们可以在两个图片上加上Canvas组件,将其Order设置为1601和1603,然后将骨骼动画的Order设置为1602即可。
当然,以上的操作要结合手动修改预制和代码控制。
RenderSortingOrder组件
这个组件可以一键将所有子节点设置为与自己相同的Order。可以设置基准Order,并设置偏移值,支持Canvas和Renderer。在非运行状态下可以勾选OverrideSorting,覆盖父节点指定的基准Order,这样父节点在一键设置Order时会跳过该节点,让该节点自己进行控制。
具体情况大家可以查看相关代码实现。