Unity中的粒子特效的 RendererQ 排序

这里接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方法。

原文地址:https://www.cnblogs.com/luguoshuai/p/10021833.html

时间: 2024-07-30 22:59:39

Unity中的粒子特效的 RendererQ 排序的相关文章

UGUI中显示粒子特效

今天在UGUI上显示粒子特效的时候遇到的一些问题,Mark一下.原理:修改特效中每一个ParticleSystem的Layer为UI,并且把ParticleSystemRenderer.sortingOrder值设置为大于Canvas中的sortingOrder值.其实就是控制两个组件 的Render Order. 1. 在UI控件上(eg: Image)显示一个粒子特效 1).首先创建一个Canvas,RenderMode = Screen Space-Camera ,然后创建一个UICame

关于Unity中的旋涡特效的制作(捕鱼达人3技术)(专题八)

Mesh 材质 Shader 1: Mesh 是网格,包括顶点,法线,纹理坐标,切线,三角形.在每一个3D模型节点里面,有一个Mesh Filter组件来提取模型里面的网格数据;2: Shader渲染算法,3D模型是按照什么方式怎么样绘制出来的;3: 材质是给渲染算法的输入数据,当我们新创建一个材质的时候,先要选Shader,在Shader文件里面关联好输入,材质实际上就是给Shader提供初始化数据的,比如Shader里面需要贴图纹理,材质就把自己的贴图纹理数据传递给自己关联的Shader,作

Unity之粒子特效参数详解——中

接<Unity之粒子特效参数详解--上>继续写,Unity之粒子特效参数详解--上链接为:http://www.cnblogs.com/yikecaidechengzhangshi/p/6991750.html 步骤二:参数设置如图 Material可以自己找一个火焰贴图,Shader参数改为:Pariticles-Additive,参图: 剩下的明天再写,今天先这样,明天回来再补充修改.

关于Unity中粒子效果的使用

粒子效果1: 游戏中会有很炫酷的特效,比如爆炸,水花,火焰等;2: unity提供粒子编辑器,方便特效人员来开发很炫酷的特效;3.粒子效果一般有专门的粒子特效师来做,我们只需要拿来用就好了,很多参数没必要掌握. Particle System组件面板 1: 粒子系统主体;2: 喷射(Emission);3: 形态(shape);4: 生命周期内的速度偏移(velocity over lifetime);5: 生命周期内的限制速度(limit velocity over lifetime);6:

【Unity 3D】学习笔记四十二:粒子特效

粒子特效 粒子特效的原理是将若干粒子无规则的组合在一起,来模拟火焰,爆炸,水滴,雾气等效果.要使用粒子特效首先要创建,在hierarchy视图中点击create--particle system即可 粒子发射器 粒子发射器是用于设定粒子的发射属性,比如说粒子的大小,数量和速度等.在创建完粒子对象后,在右侧inspector视图中便可以看到所有的粒子属性: emit:是否是使用粒子发射器. min size:粒子最小尺寸. max size:粒子最大尺寸. min energy:粒子的最小生命周期

Unity之粒子特效参数详解——上

如需转载请保留本文链接. Unity版本号:5.5.0 参考书籍:<Unity5.x从入门到精通> 参考资料:Unity官方API 参考文章: 1.http://jingyan.baidu.com/article/380abd0a77c5041d90192c19.html 2.http://www.cnblogs.com/qinghuaideren/p/3597666.html?utm_source=tuicool&utm_medium=referral 目标:做出一个篝火效果,最终结

UGUI中粒子特效与UI的遮挡问题

问题背景: 在做主线任务时发现完成任务后的特效显示穿透上面的UI层,不美观,策划不乐意了,抓紧解决下 解决思路: 首先讲下影响渲染顺序的因素: 能够影响渲染顺序的因素有:1.Camera Depth     相机组件上设置的相机深度,深度越大越靠后渲染. 2.Sorting Layer      在Tags & Layers设置中可见 3.Order In Layer 相对于Sorting Layer的子排序,用这个值做比较时只有都在同一层时才有效.4.RenderQueue     Shade

Unity之一天一个技术点(十)---UI添加粒子特效

最近给UI添加粒子特效时,总是被UI遮挡, 解决方法是: 因为粒子系统的渲染顺序列默认为3000,而NGUI的渲染顺序默认也是从3000开始,当有嵌套的panel时或者Depth更高的panel时,GUI的渲染顺序会高于3000, 解决办法是, 1.修改Ngui中的UIPanel脚本中的默认的RenderQueue, 调整到3000以下,这样就不会遮挡住粒子特效了,当有的窗口需要显示在特效上面时,在检视面板中把该窗口的Renderer Q选项调整为Start At,值为3000以上,就可以解决,

【Unity技巧】Unity中的优化技术

写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得的~Digital Tutors是一个非常棒的教程网站,包含了多媒体领域很多方面的资料,非常酷!除此之外,还参考了Unity Cookie中的一个教程.还有很多其他参考在下面的链接中. 这篇文章旨在简要地说明一下常见的各种优化策略.不过对每个基础有非常深入地讲解,需要的童鞋可以自行去相关资料. 还有一些我认为非常好的参考文章: Performance Optimization for Mobile Devices