Unity NGUI 粒子的排序

Unity NGUI系统中是没有对粒子进行排序的,如:

 

 

 

怎么解决这个问题呢?

思路是把粒子的渲染层级,相对于UI组件的层级进行一个偏移。

解决后的效果如下:

 

 

 

 

代码如下:

新增脚本 UIRenderQueueSorter.cs:

 

  1 using System.Collections.Generic;
  2 using UnityEngine;
  3 
  4 public class UIRenderQueueSorter : MonoBehaviour
  5 {
  6     [SerializeField]
  7     UIWidget m_source;
  8     [SerializeField]
  9     int m_offset;
 10     [SerializeField]
 11     bool m_setToSameRQ = true;
 12 
 13     List<Material> m_mats;
 14     UIPanel m_panel;
 15     int m_beginRQ, m_maxRQ;
 16 
 17 
 18     public UIWidget Source
 19     {
 20         get => m_source;
 21         set => m_source = value;
 22     }
 23 
 24     public int Offset
 25     {
 26         get => m_offset;
 27         set => m_offset = value;
 28     }
 29 
 30 
 31     void OnEnable()
 32     {
 33         Initialize();
 34     }
 35 
 36     public void Initialize()
 37     {
 38         m_beginRQ = -1;
 39         m_maxRQ = 0;
 40 
 41         m_panel = gameObject.GetComponentInParent<UIPanel>();
 42         if (!m_panel)
 43         {
 44             enabled = false;
 45             return;
 46         }
 47 
 48         if (!m_panel.m_rqSorter.Contains(this))
 49             m_panel.m_rqSorter.Add(this);
 50 
 51         if (m_mats == null)
 52             m_mats = new List<Material>();
 53         else
 54             m_mats.Clear();
 55         Renderer[] renders = transform.GetComponentsInChildren<Renderer>(true);
 56         for (int i = 0; i < renders.Length; i++)
 57         {
 58             var r = renders[i];
 59             if (!r)
 60                 continue;
 61             if (r is ParticleSystemRenderer psr)
 62             {
 63                 psr.sortingOrder = 0;
 64                 if (psr.trailMaterial)
 65                     m_mats.Add(psr.trailMaterial);
 66             }
 67             if (r.sharedMaterial)
 68                 m_mats.Add(r.sharedMaterial);
 69         }
 70 
 71         m_mats.Sort((a, b) => a.renderQueue.CompareTo(b.renderQueue));
 72     }
 73 
 74     public int UpdateRendererQueue(int panelRQ)
 75     {
 76         if (m_mats.Count < 1)
 77             return 0;
 78 
 79         int rq = Source && Source.drawCall ? Source.drawCall.renderQueue : panelRQ;
 80         rq += Offset;
 81         if (m_beginRQ == rq)
 82             return m_maxRQ;
 83 
 84         m_beginRQ = rq;
 85         if (m_setToSameRQ)
 86         {
 87             for (int i = 0; i < m_mats.Count; ++i)
 88             {
 89                 var mat = m_mats[i];
 90                 if (mat)
 91                     mat.renderQueue = m_beginRQ;
 92             }
 93             m_maxRQ = m_beginRQ;
 94         }
 95         else
 96         {
 97             int tempRQ = -1, addRQ = 0;
 98             for (int i = 0; i < m_mats.Count; ++i)
 99             {
100                 var mat = m_mats[i];
101                 if (mat == null)
102                     continue;
103                 if (tempRQ != mat.renderQueue)
104                 {
105                     tempRQ = mat.renderQueue;
106                     ++addRQ;
107                 }
108                 m_maxRQ = m_beginRQ + addRQ;
109                 mat.renderQueue = m_maxRQ;
110             }
111         }
112         return m_maxRQ;
113     }
114 
115     void OnDestroy()
116     {
117         if (m_panel && m_panel.m_rqSorter != null)
118             m_panel.m_rqSorter.Remove(this);
119     }
120 
121 }

 

同时修改NGUI 的 UIPanel.cs

 1     public List<UIRenderQueueSorter> m_rqSorter = new List<UIRenderQueueSorter>();
 2 
 3     void LateUpdate ()
 4     {
 5 #if UNITY_EDITOR && !UNITY_5_5_OR_NEWER
 6         if (mUpdateFrame != Time.frameCount || !Application.isPlaying)
 7 #else
 8         if (mUpdateFrame != Time.frameCount)
 9 #endif
10         {
11             mUpdateFrame = Time.frameCount;
12 
13             // Update each panel in order
14             for (int i = 0, imax = list.Count; i < imax; ++i)
15                 list[i].UpdateSelf();
16 
17             int rq = 3000;
18 
19             // Update all draw calls, making them draw in the right order
20             for (int i = 0, imax = list.Count; i < imax; ++i)
21             {
22                 UIPanel p = list[i];
23 
24                 if (p.renderQueue == RenderQueue.Automatic)
25                 {
26                     p.startingRenderQueue = rq;
27                     p.UpdateDrawCalls(i);
28                     rq += p.drawCalls.Count;
29 
30                     // [dev] uipanel 的 render queue向后偏移
31                     int maxRq = 0;
32                     for (int k = 0; k < p.m_rqSorter.Count; k++)
33                         maxRq = Mathf.Max(maxRq, p.m_rqSorter[k].UpdateRendererQueue(rq));
34                     rq = Mathf.Max(rq, maxRq + 1);
35                 }
36                 else if (p.renderQueue == RenderQueue.StartAt)
37                 {
38                     p.UpdateDrawCalls(i);
39                     if (p.drawCalls.Count != 0)
40                         rq = Mathf.Max(rq, p.startingRenderQueue + p.drawCalls.Count);
41                 }
42                 else // Explicit
43                 {
44                     p.UpdateDrawCalls(i);
45                     if (p.drawCalls.Count != 0)
46                         rq = Mathf.Max(rq, p.startingRenderQueue + 1);
47                 }
48             }
49         }
50     }

 

用法:

1                     // 特效排序
2                     var sorter = m_effect.AddComponent<UIRenderQueueSorter>();
3                     sorter.Source = m_itemTexture;
4                     sorter.Offset = 1;
5                     sorter.Initialize();

此脚本将挂在需要排序的粒子的父节点上:

 

转载请注明出处:https://www.cnblogs.com/jietian331/p/10944356.html

posted @ 2019-05-29 16:00  孤独の巡礼  阅读(503)  评论(0编辑  收藏  举报