本文介绍如何让粒子显示在NGUI的图片之间,效果如第1张图那样(第2张图是正常情况下的显示)
先把下面2个脚本文件放到项目里:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
// ***************************************************************************
// Author : LZ
// This is a invisible UIWidget which always monopolize a render queue.
// ***************************************************************************
public class UIInvisibleWidget : UIWidget
{
private Texture2D mTex;
private Material mMat;
protected override void Awake()
{
base.Awake();
mTex = new Texture2D(0, 0);
mChanged = false;
fillGeometry = false;
geometry.verts.Add(new Vector3(1f, 0, 0));
geometry.verts.Add(new Vector3(2f, 0, 0));
geometry.verts.Add(new Vector3(3f, 0, 0));
geometry.verts.Add(new Vector3(4f, 0, 0));
geometry.ApplyTransform(Matrix4x4.identity, false);
geometry.uvs.Add(Vector2.zero);
geometry.uvs.Add(Vector2.up);
geometry.uvs.Add(Vector2.one);
geometry.uvs.Add(Vector2.right);
geometry.cols.Add(Color.white);
geometry.cols.Add(Color.white);
geometry.cols.Add(Color.white);
geometry.cols.Add(Color.white);
}
public override Texture mainTexture
{
get
{
return mTex;
}
set
{
}
}
public override Material material
{
get
{
return mMat;
}
set
{
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
// ***************************************************************************
// Author : LZ
// ***************************************************************************
public class BindRenderQueueToWidget : MonoBehaviour
{
public UIWidget bindTarget;
public int renderQueue_ReadOnly;
private Renderer _renderer;
void Start()
{
_renderer = gameObject.GetComponent<Renderer>();
}
void OnWillRenderObject()
{
if (bindTarget == null || bindTarget.drawCall == null || _renderer == null || _renderer.material == null)
{
return;
}
renderQueue_ReadOnly = bindTarget.drawCall.renderQueue;
_renderer.material.renderQueue = renderQueue_ReadOnly;
}
}
用法:
在UIPanel下添加一个空物体A并挂上脚本UIInvisibleWidget,调整它的depth还有所在的Panel,然后给目标粒子发射器添加脚本BindRenderQueueToWidget,将A拖到bindTarget上。运行游戏,此时粒子的显示层级跟UIInvisibleWidget完全保持一致,想调整粒子显示层级,改动UIInvisibleWidget就好了。
下面简单解说一下原理:
NGUI使用RenderQueue来控制各种Widget的显示顺序,对所有Widget,根据Panel和Widget的depth每帧排序一次,并根据排序结果赋予RenderQueue值,从3000开始依次递增,可以在菜单“NGUI/Open/Draw Call Tool”里查看当前的RenderQueue分配情况。RenderQueue值越大的物体越晚渲染,显示也越靠前(就像画油画一样,层层覆盖)。
Unity规定透明物体的RenderQueue是3000,RenderQueue值可以在Shader里指定,也可以在运行时修改。我们正常情况下使用的粒子,其RenderQueue都是3000,会被RenderQueue值更高的NGUI遮挡也就理所当然了。
UIInvisibleWidget是一个特殊的UIWidget,它被NGUI当做一个有内容的Widget且不和任何其他Widget共享材质,会被分配一个唯一的RenderQueue,虽然它什么都不会显示。注意每个UIInvisibleWidget会占用一个DrawCall,请谨慎使用。
BindRenderQueueToWidget每帧把自己的RenderQueue改为目标Widget的RenderQueue,这样就达到了我们用NGUI的depth控制particle显示层级的目的。