需求

  1. 显示:UI 需要与特效共同显示,且能方便地调整前后关系。
  2. 操作:对 UI 的操作需要与显示的层级对应,不会出现错误的穿透问题。

网上大多数人只研究了第一点,但在实际项目中必须要解决第二点,否则会出现莫明其妙的操作 Bug。

前提

UGUI 与特效能同时显示的前提是都使用相同的方式渲染与排序。

因此 Canvas 的 Render Mode 可以设置为 Screen Space - CameraWorld Space,即使用 Camera 来渲染 UI。

原理

不论是显示还是操作,都是受不同的属性影响。 有 SortingLayer、SortingOrder、Z 等方便修改的属性,还有 RenderQueue 之类不方便修改的属性。

UGUI和特效模型混排的解决方案 这篇文章讲解地比较详细。

因为属性需要人工在 Unity 界面中修改,所以只考虑方便修改的属性。

  1. 显示:SortingLayer > SortingOrder > Z
  2. 操作:SortingLayer > SortingOrder > Graphic.depth > Z

注:操作相关的属性比较来自于 UGUI 源码 中的 EventSystem.csGraphicRaycaster.cs

Graphic.depth 是什么?官方文档解释如下:

The depth is relative to the first root canvas. Here is an example hierarchy and the corresponding graphics depth: Canvas Graphic <- 1 Graphic <- 2 Nested Canvas Graphic <- 3 Graphic <- 4 Graphic <- 5

Unity - Scripting API: UI.Graphic.depth

实际上检查源码发现,Graphic.depth 是 Canvas 下继承自 Graphic 的 UI 组件的深度遍历顺序。

但是由于 EventSystem 在比较 Graphic.depth 时未考虑是否是同一个 GraphicRaycaster(Canvas) 下的 Graphic, 因此导致无法在不同 Canvas 下使用此属性。

方案

由于上述 EventSystem 的限制,导致只能使用 SortingLayer 或 SortingOrder。 由于 SortingLayer 需要预先定义,那么剩下的选项只有 SortingOrder。

  1. 显示:SortingOrder > Z
  2. 操作:SortingOrder

那么在实际使用中,需要管理不同 Canvas 的 SortingOrder。即按照显示顺序设置 Canvas 的 SortingOrder,同时为 Canvas 下的粒子增加 SortingGroup 组件并设置相同的 SortingOrder,此时再修改 Z 值来决定粒子与 UI 之间的显示顺序。

工具

如果涉及到原有 UI 改造,那么建议编写几个工具批量处理:

  1. 统一 UI 结构工具,保证结构与属性都一致,如坐标取整、缩放统一以保证粒子显示正常等等。
  2. UI 自动查找特效并增加 SortingGroup 工具,方便美术调整。