1. 程式人生 > >Unity中的粒子特效的 RendererQ 排序

Unity中的粒子特效的 RendererQ 排序

ret move 發的 field .cn raw The ans 介紹

這裏接https://www.cnblogs.com/luguoshuai/p/10021660.html

這裏介紹兩套粒子排序的方法。

首先聲明,這兩套排序方法均不是本人所寫,是在項目開發的過程當中,看到同事的設計,然後我就記錄了下來了,作為後續的學習與使用。

方法一:

 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 
 4 public class UIRenderQueueSorter : MonoBehaviour
 5 {
 6     [SerializeField]
 7     UIWidget m_source;  //
基礎RendererQ,粒子的 RendererQ 均是在此基礎上遞增的 8 [SerializeField] 9 int m_offset; //每次遞增的幅度 10 [SerializeField] 11 List<Renderer> m_renderers = new List<Renderer>(); 12 13 public void Initialize() 14 { 15 Renderer[] renders = transform.GetComponentsInChildren<Renderer>(true
); 16 m_renderers.AddRange(renders); 17 } 18 19 void Update() 20 { 21 if (m_source && m_renderers.Count > 0) 22 { 23 for (int i = 0; i < m_renderers.Count; i++) 24 { 25 Renderer r = m_renderers[i]; 26 if
(r && r.sharedMaterial && m_source.drawCall != null) 27 r.sharedMaterial.renderQueue = m_source.drawCall.renderQueue + m_offset; 28 } 29 } 30 } 31 32 public void AddRenderer(Renderer r) 33 { 34 if (!m_renderers.Contains(r)) 35 { 36 m_renderers.Add(r); 37 } 38 } 39 40 public void ClearAllRenderers() 41 { 42 m_renderers.Clear(); 43 } 44 45 public UIWidget Source 46 { 47 set { m_source = value; } 48 } 49 50 public int Offset 51 { 52 set { m_offset = value; } 53 } 54 }

用法介紹,將該腳本掛載到粒子特效的父級對象上,使用的時候,只需要調用一下Initialize()方法即可。

方法二:

這個其實是對NGUI的一個簡答擴展,粒子的 RendererQ 是以Panel為單位來計算的

對NGUI的修改,添加如下變量:

1     public List<UIParticlesEffectAutoSort> uiEffectList = new List<UIParticlesEffectAutoSort>();

修改NGUI的 LateUpdate 方法為如下:

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

UIParticlesEffectAutoSort:

 1 using UnityEngine;
 2 using System.Collections.Generic;
 3 
 4 public class UIParticlesEffectAutoSort : MonoBehaviour
 5 {
 6     protected UIPanel panel;
 7     protected List<Material> mats = new List<Material>();
 8     int beginRenderQ = -1, totalRenderQ = 0;
 9     void Start()
10     {
11         panel = gameObject.GetComponentInParent<UIPanel>();
12         if (panel == null)
13         {
14             enabled = false;
15         }
16         else
17         {
18             Renderer[] rds = gameObject.GetComponentsInChildren<Renderer>(true);
19             for (int i = 0; i < rds.Length; ++i)
20             {
21                 for (int j = 0; j < rds[i].sharedMaterials.Length; ++j)
22                 {
23                     if (rds[i].sharedMaterials[j] != null)
24                         mats.Add(rds[i].sharedMaterials[j]);
25                 }
26             }
27             mats.Sort(delegate(Material a, Material b)
28             {
29                 return a.renderQueue.CompareTo(b.renderQueue);
30             });
31             panel.uiEffectList.Add(this);
32         }
33     }
34     void OnDestroy()
35     {
36         if (panel != null)
37             panel.uiEffectList.Remove(this);
38     }
39     public int UpdateRendererQueue(int rq)
40     {
41         if (panel == null)
42             return 0;
43         if (mats.Count > 0)
44         {
45             if (beginRenderQ != rq)
46             {
47                 beginRenderQ = rq;
48                 int tempRenderQ = -1, addRenderQ = 0;
49                 for (int i = 0; i < mats.Count; ++i)
50                 {
51                     if (mats[i] == null)
52                         continue;
53                     if (tempRenderQ != mats[i].renderQueue)
54                     {
55                         tempRenderQ = mats[i].renderQueue;
56                         ++addRenderQ;
57                     }
58                     mats[i].renderQueue = beginRenderQ + addRenderQ;
59                 }
60                 totalRenderQ = addRenderQ + 1;
61             }
62             return totalRenderQ;
63         }
64         return 0;
65     }
66 }

用法:將該腳本掛載到粒子特效的父級對象上即可。

需要註意的是,這兩個方法都是調整的 sharedMaterials,如果在使用的過程中發現粒子的層級不正確,試著調整materials即可。

比如,方法二:

 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 
 4 public class UISelfParticalEffectAutoSort : UIParticlesEffectAutoSort
 5 {
 6     void Start()
 7     {
 8         panel = gameObject.GetComponentInParent<UIPanel>();
 9         if (panel == null)
10         {
11             enabled = false;
12         }
13         else
14         {
15             Renderer[] rds = gameObject.GetComponentsInChildren<Renderer>(true);
16             for (int i = 0; i < rds.Length; ++i)
17             {
18                 for (int j = 0, jMax = rds[i].materials.Length; j < jMax; ++j)
19                 {
20                     if (rds[i].materials[j] != null)
21                         mats.Add(rds[i].materials[j]);
22                 }
23             }
24             mats.Sort(delegate(Material a, Material b)
25             {
26                 return a.renderQueue.CompareTo(b.renderQueue);
27             });
28             panel.uiEffectList.Add(this);
29         }
30     }
31     void OnDestroy()
32     {
33         if (panel != null)
34             panel.uiEffectList.Remove(this);
35         for (int i = mats.Count - 1; i >= 0; --i)
36             GameObject.Destroy(mats[i]);
37         mats.Clear();
38     }
39 }

主要看Start方法。

Unity中的粒子特效的 RendererQ 排序