unity实用技能,控制renderQueue解决NGUI与Unity3D物体渲染顺序问题

NGUI与Unity3D物体渲染顺序问题,做UI的同学应该都遇到过。主要指的是UI与Unity制作的特效、3D人物等一同显示时的层次问题。

之前邓老师就这一问题,专门做了一次分享。邓老师在分享时也指出了这类问题的根源:由于UI与特效等都是以transparent方式渲染,而Unity与NGUI在管理同是透明物体的render queue时实际上互相没有感知,于是引出排序问题。邓老师介绍了以Render To Texture方式解决这一问题的一种方法,文档见svn: /wlgame_proj/trunk/Client/Doc/规范文档/UI上的特效显示.docx

 

然而使用rtt解决这类问题总感觉过重,且不够灵活;而且rtt为了兼顾效率,纹理不可能设置太大,所以也导致了渲染精度降低、细节丢失的问题。

今天尝试了另一种思路来解决这一问题:直接控制Unity中特效的render queue值,来达到使得UI、特效按照我们希望的顺序进行渲染的目的。

先上效果图,数字标注了不同的层次,按照0-7的顺序叠加:

 

测试的工程地址:

\\......\......\03.客户端\frank\UISandwichWithParticle.zip

测试场景为Assets\TestScene.unity。

 

另外这一工程中也包含了一个以邓老师的方式解决这一问题的示例,场景为Assets\TestScene_orig.unity。

首先参考一下邓老师方法中实现这类叠加后的Draw Call细节:

 

 

可以看到,因为所有元素最终都是以NGUI的元素进行管理的,draw call非常清晰,一层UI夹一层rtt纹理,render queue从3000开始依次排序下来,标准的多层三明治结构。

再来看另一种方式下UI的draw call细节: 

 

这种方式下,UI和特效还是分开渲染的,所以NGUI的Draw Call统计里只能看到UI的4个dc。注意,这里手动设置了每个UI的render queue的值,分别是3000、3002、3004、3006,和上面的dc顺序参照相对应的关系,可以发现是把用于特效渲染的render queue值(3001、3003、3005)给预留了出来。

 http://zzido.cn/home/article/view/id/65272.html

这里先插播一下关于设置UI的draw call的细节,也是这一方法中繁琐的部分。我们知道NGUI会将采用同样材质的widget合并到同一个draw call中进行渲染。然而在我们这个需求中,这一功能导致了无法在widget之间插入其它渲染队列的问题,也就是原始的三明治问题。如果只是涉及到UI控件之间的穿插,NGUI可以通过depth设置来解决:

如果是使用同一材质的多个控件设置了不同的depth值,则NGUI还是将这些控件合并为同一个draw call,而在内部进行了排序; http://m.zzido.cn/home/article/view/id/65273.html
如果设置了不同depth的多个控件,穿插使用了不同的材质,则NGUI会将其打散为不同的draw call,顺序即按照depth指定。邓老师的方式就用到的这一特性,其一共使用了2种材质而设置不同depth形成穿插关系,于是被打散成了7个dc。

http://www.zzido.cn/home/article/view/id/65272.html
我采用的方式,属于上述第一种情况,无法简单用depth设置来解决。为了将一个NGUI自动合并的dc打散,有多种hack的方式,这里选择的是手动给每个我们希望打散到不同dc的widget再添加一个panel的方式。增加panel原则上并不推荐,然而针对这一需求,实际上增加的空panel并不影响性能。其结果就是上图中所示。

 http://m.zzido.cn/home/article/view/id/65272.html

在为每个归属于不同层次的widget指定了所属的render queue顺序之后,剩下的就是为每个unity的特效指定应归属的render queue。

这里引入了一个脚本:RenderQueueModifier.cs( https://www.zzido.cn/home/article/view/id/65272.html )。使用时,需要将这一脚本拖到对应的Unity的3D物体上

 

指定一个作为target的widget,以及排序方式即可。上图的例子中,指定的target为card1,type为FRONT,含义是将这一特效指定为在Card1控件的前面。

其原理也较为简单,直接贴源码: http://zzido.cn/home/article/view/id/65273.html

using UnityEngine;

using System.Collections;

 

public class RenderQueueModifier : MonoBehaviour

{

public enum RenderType

{

FRONT,

BACK

}


public UIWidget m_target = null;

public RenderType m_type = RenderType.FRONT;

柳断肠处长向尊前悲老大有人夫婿擅侯王当时只受声名累贵戚名豪竞延致照花前后镜花面交相  http://zzido.cn/home/article/view/id/65274.html

映新帖绣罗襦双双金鹧鸪折戟沈沙铁未销自将磨洗认前朝东风不与周郎便铜雀春深锁二乔阵阵轻寒细马骄竹林茅店小帘招东风已绿南溪水更染溪南万柳条峥嵘赤云西日脚下平地柴门鸟雀噪归客千里至之死矢靡它母也天只不谅人 http://www.zzido.cn/home/article/view/id/65274.html

只泛彼柏舟芷葺兮荷屋缭之兮杜衡合百草兮实庭建芳馨兮廡门中泠南畔石盘陀古来出没随涛波试登绝顶望乡国江南江北青山多中原干戈古亦闻岂有逆胡传子孙遗民忍死望恢复几处今宵垂泪痕中州盛日闺门多暇记得偏重三五铺翠冠儿捻金雪柳簇带争济楚如今憔悴风鬟霜鬓怕见夜间出去不如向帘 http://m.zzido.cn/home/article/view/id/65274.html 儿底下听

人笑语终愧巢与由未能易其节沈饮聊自适放歌破愁绝众芳摇落独暄妍占尽风情向小园疏影横斜水清浅暗香浮动月黄昏众鸟高飞尽孤云独去闲相看两不厌只有敬亭山重过阊门万事非同来何事不同归梧桐半 https://www.zzido.cn/home/article/view/id/65274.html  清霜后头白鸳鸯失伴飞重湖

叠巘清嘉有三秋桂子十里荷花羌管弄晴菱歌泛夜嬉嬉钓叟莲娃千骑拥高牙乘醉听箫鼓吟赏烟霞异日图将好景归去凤池夸重泉若有双鱼寄好知他年来苦乐与谁相倚我自中宵成转侧忍听湘弦重理待结个他生知已还怕两人俱薄命再缘悭剩月零风里清泪尽纸灰起昼出耘田夜绩麻村庄儿女各当家童孙未解供耕织也傍桑阴学种瓜朱门歌舞争新态绿绮尘埃试拂弦常恨闻名不相识相逢罇酒盍留连朱弦已为佳人绝青眼聊因美酒横万里归船弄长笛


Renderer[] _renderers;

int _lastQueue = 0;


void Start ()

{

_renderers = GetComponentsInChildren<Renderer>();

}


void FixedUpdate() {

if( m_target == null || m_target.drawCall == null )

return;

int queue = m_target.drawCall.renderQueue;

queue += m_type == RenderType.FRONT ? 1 : -1;

if( _lastQueue != queue )

{

_lastQueue = queue;


foreach( Renderer r in _renderers )

{

r.material.renderQueue = _lastQueue;

}

}

}

}

 

可以看到,原理上就是直接修改这一特效下所有renderer组建中的material的renderQueue值,来按照需要指定。

还是以上面截图的示例为例,Card1位于NGUI指定的render queue位置3000,则这个特效所在的render queue为3001,而在它之后render queue为3002的控件正好是控件Mask1。

所以和邓老师方案最终的render queue效果相比较,其实算是殊途同归,可以在不使用Render To Texture的情况下,达到更好的效果。

TODO:

偷懒所以手动添加的panel直接放在widget上,导致ngui会提示一条错误日志。这个按照规范,将panel与widget设为父子结构即可 http://www.zzido.cn/home/article/view/id/65273.html
RenderQueueModifier.cs脚本还有优化的余地,特别是可以增强编辑器支持,来达到不启动游戏即可实时查看叠加效果的功能。
这个方案测试是在老版本的NGUI3.0.6中进行的。3.6版的新NGUI中,引入了手动修改render queue的功能,会更加方便为每个ui指定所属的render queue。

posted @ 2019-05-11 23:18  th76h45f  阅读(2203)  评论(0编辑  收藏  举报