1. 程式人生 > >在NGUI中插入粒子特效(ParticleSystem)

在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顯示層級的目的。