在NGUI中插入粒子特效(ParticleSystem)
本文介紹如何讓粒子顯示在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顯示層級的目的。