天天看點

UI特效層級

實作的功能是可以讓特效顯示在UI層級之間或者一直保持在UI最前面。

不管是NGUI還是特效最終都是通過RenderQueue控制的。

問題是我們怎麼擷取一個特效RenderQueue讓他剛好在UI元素之間?

通過NGUI Texture2D(單獨的drawcall)的顯示規則來擷取RenderQueue然後指派給特效,相當于特效的顯示規則和Texture2D一樣了。

這裡需要注意特效的sortingOrder必須和UI一樣。

代碼如下

using UnityEngine;

[RequireComponent(typeof(UIInvisibleWidget))]
public class UIInVisibleSort : MonoBehaviour
{
    // 是否顯示在UI的最上層
    public bool isTop = true;
    // 用來調試顯示
    public int renderQueue_ReadOnly;
    // 特效的渲染
    private Renderer[] _renderers;
    // 通過NGUI配置設定的UIWidget
    private UIInvisibleWidget _widget;
    // 是否已經排序了
    private bool _isSort = false;
    // 是否晚一幀調整特效層級
    private bool _IsFrameDelay = false;

    public void SortTop()
    {
        int maxDepth = _widget.depth;
        if (isTop)
        {
            UIPanel parentPanel = transform.GetComponentInParent<UIPanel>();
            if (parentPanel)
                maxDepth = parentPanel.GetMaxUIWightDepth() + 1;
        }
        Sort(maxDepth);
    }

    public void Sort(int depth)
    {
        _widget.depth = depth;
        _isSort = true;
    }

    void Awake()
    {
        _widget = gameObject.GetComponent<UIInvisibleWidget>();
        _renderers = gameObject.GetComponentsInChildren<Renderer>();
    }

    void Start()
    {
        _IsFrameDelay = true;
        SortTop();
    }

    void Update()
    {
        if (_IsFrameDelay)
        {
            _IsFrameDelay = false;
            return;
        }
        if (!_isSort)
            return;

        if (_widget == null || _widget.drawCall == null || _renderers == null)
        {
            return;
        }

        _isSort = false;

        renderQueue_ReadOnly = _widget.drawCall.renderQueue;
        foreach(Renderer render in _renderers)
        {
            //render.sortingOrder = 0;
            render.material.renderQueue = renderQueue_ReadOnly;
        }
    }

    [ContextMenu("ReExcute")]
    void ReExcute()
    {
        _isSort = true;
    }

#if UNITY_EDITOR
    void OnValidate()
    {
        _isSort = true;
		if (_widget)
		{
			_widget.drawCall.renderQueue = renderQueue_ReadOnly;
		}
    }
#endif

}


           
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class UIInvisibleWidget : UIWidget
{
    private Texture2D mTex;
    private Material mMat;

    protected override void Awake()
    {
        base.Awake();
        height = 0;
        width = 0;
        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);
        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
        {

        }
    }
}