UGUI(九)UI粒子特效

来源:互联网 发布:网络言情经典小说作家 编辑:程序博客网 时间:2024/05/19 18:14

我们工作中使用的次时代界面NGUI,UGUI,在游戏窗口大小发生变化的时候,细心观察界面元素它的大小并没有变化(这个大小相对于电脑屏幕)。

 

但是3D场景中的模型大小是变化的,而粒子也一样会发生变化,如果我们想在UI上使用系统自带的粒子系统,这样就无法兼容各种大小的游戏窗口,因为无法使用系统粒子,就只能采用序列图或者摄像机渲染纹理的方式去做特效,这样做不是不可以,但是前者资源量大,后者不好管理。

 

那么我们能不能做到把粒子系统做的特效保持固定的大小呢?其实是可以的,在屏幕大小发生变化的时候,重新计算粒子顶点的缩放,保持它的大小不变,这样就可以和UI保持一致。

 

看下图,粒子和界面元素在同一层级,屏幕大小发生变化的时候,粒子也不会变化:

UGUI(九)UI粒子特效
制作环境:

1.在UI层的Canvas下。

2.给特效父节点挂上ParticleScale脚本(传人一些参数到材质球中)。

3.粒子shader使用UI_Particles/Alpha Blended(根据官方shader修改而来)。

4.粒子的渲染模式RenderMode选为Mesh。

 

ParticleScale脚本如下:

  1. using UnityEngine;  
  2. using System.Collections;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using UnityEngine;  
  8.   
  9. ///   
  10. /// 添加到UI层粒子的父节点  
  11. /// 适用于UGUI,NGUI  
  12. ///   
  13. [ExecuteInEditMode]  
  14. public class ParticleScale MonoBehaviour   
  15.  
  16.     private Transform m_transform;  
  17.     private List m_matList new List();  
  18.     private Camera m_uiCamera;  
  19.   
  20.     void Start()  
  21.      
  22.         m_transform transform;  
  23.         m_matList.Clear();  
  24.         GetChildMaterial(m_transform, ref m_matList);  
  25.           
  26.         m_uiCamera GameObject.Find("ui_camera").GetComponent();  
  27.   
  28.         MeshRenderer mr m_transform.GetComponent();  
  29.         if (null == mr)m_transform.gameObject.AddComponent();  
  30.      
  31.   
  32.     private void GetChildMaterial(Transform parent, ref List list)  
  33.      
  34.         foreach (Transform child in parent)  
  35.          
  36.             Renderer mat child.GetComponent();  
  37.             if (null != mat && null != mat.sharedMaterial)  
  38.              
  39.                 list.Add(mat.sharedMaterial);  
  40.              
  41.             GetChildMaterial(child, ref list);  
  42.          
  43.      
  44.   
  45.     public void OnWillRenderObject()  
  46.      
  47.         if (m_matList.Count == 0Start();  
  48.         foreach (Material item in m_matList)  
  49.          
  50.             item.SetVector("_Center"m_transform.position);  
  51.             item.SetVector("_Scaling"m_transform.lossyScale);  
  52.             item.SetMatrix("_Camera"m_uiCamera.worldToCameraMatrix);  
  53.             item.SetMatrix("_CameraInv"m_uiCamera.worldToCameraMatrix.inverse);  
  54.          
  55.      
  56.  

 

UI_Particles/Alpha Blended代码如下:

  1. Shader "UI_Particles/Alpha Blended"  
  2.     Properties  
  3.         _TintColor ("Tint Color"Color) (0.5,0.5,0.5,0.5 
  4.         _MainTex ("Particle Texture"2D) "white" {}  
  5.         _InvFade ("Soft Particles Factor"Range(0.01,3.0)) 1.0  
  6.      
  7.   
  8.     Category  
  9.         Tags   
  10.           
  11.             "Queue"="Transparent"   
  12.             "IgnoreProjector"="True"  
  13.             "RenderType"="Transparent"  
  14.          
  15.         // 源rgb*a 背景rgb*(1-源a)  
  16.         Blend SrcAlpha OneMinusSrcAlpha  
  17.         // 显示透明度大于0.01的  
  18.         AlphaTest Greater .01  
  19.         ColorMask RGB  
  20.         // 不裁剪前后  
  21.         Cull Off  
  22.         Lighting Off   
  23.         // 关闭深度缓存,作为面片显示的特效不需要缓存深度  
  24.         ZWrite Off  
  25.         // 指定顶点数据源映射到目标硬件  
  26.         BindChannels  
  27.             Bind "Color"color  
  28.             Bind "Vertex"vertex  
  29.             Bind "TexCoord"texcoord  
  30.          
  31.       
  32.         SubShader  
  33.             Pass  
  34.           
  35.                 CGPROGRAM  
  36.                 #pragma vertex vert  
  37.                 #pragma fragment frag  
  38.                 #pragma fragmentoption ARB_precision_hint_fastest  
  39.                 #pragma multi_compile_particles  
  40.               
  41.                 #include "UnityCG.cginc"  
  42.   
  43.                 sampler2D _MainTex;  
  44.                 fixed4 _TintColor;  
  45.               
  46.                 struct appdata_t  
  47.                     float4 vertex POSITION;  
  48.                     fixed4 color COLOR;  
  49.                     float2 texcoord TEXCOORD0;  
  50.                 };  
  51.   
  52.                 struct v2f  
  53.                     float4 vertex POSITION;  
  54.                     fixed4 color COLOR;  
  55.                     float2 texcoord TEXCOORD0;  
  56.                     // 开启软边粒子时,需要用到投影纹理  
  57.                     #ifdef SOFTPARTICLES_ON  
  58.                     float4 projPos TEXCOORD1;  
  59.                     #endif  
  60.                 };  
  61.               
  62.                 float4 _MainTex_ST;  
  63.                 float3 _Scaling;  
  64.                 float4 _Center;  
  65.                 float4x4 _Camera;  
  66.                 float4x4 _CameraInv;  
  67.   
  68.                 v2f vert (appdata_t v)  
  69.                  
  70.                     v2f o;  
  71.                     if(_Scaling.x != 0 
  72.                      
  73.                         //【摄像机空间】转到【世界空间】  
  74.                         float4 objV mul(_CameraInv, v.vertex);  
  75.                         // 控制顶点中心点  
  76.                         objV.xyz -= _Center;  
  77.                         // 控制顶点缩放,当屏幕大小发生改变的时,根据lossyScale来计算新的顶点  
  78.                         objV.xyz float3(_Scaling.x objV.x, _Scaling.y objV.y, _Scaling.z objV.z);  
  79.                         // 控制顶点中心点  
  80.                         objV.xyz += _Center;  
  81.                         // 【世界坐标】转到【摄像机坐标】  
  82.                         o.vertex mul(_Camera, objV);  
  83.                         // END OF CHANGE  
  84.                         o.vertex mul(UNITY_MATRIX_MVP, o.vertex);  
  85.                     }else 
  86.                         // 官方shader直接运行这里  
  87.                         o.vertex mul(UNITY_MATRIX_MVP, v.vertex);   
  88.                      
  89.                     #ifdef SOFTPARTICLES_ON  
  90.                     // 计算顶点在屏幕的纹理  
  91.                     o.projPos ComputeScreenPos (o.vertex);  
  92.                     COMPUTE_EYEDEPTH(o.projPos.z);  
  93.                     #endif  
  94.                     o.color v.color;  
  95.                     o.texcoord TRANSFORM_TEX(v.texcoord,_MainTex);  
  96.                     return o;  
  97.                  
  98.   
  99.                 sampler2D _CameraDepthTexture;  
  100.                 float _InvFade;  
  101.               
  102.                 fixed4 frag (v2f i) COLOR  
  103.                  
  104.                     // 开启软边粒子时,会根据场景的深度调整粒子的透明度,确保无黑线  
  105.                     #ifdef SOFTPARTICLES_ON  
  106.                     // 对摄像机深度图进行采样  
  107.                     float4 texProj tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos));  
  108.                     // 【Z深度缓存信息】转为【场景线性深度】  
  109.                     float sceneZ LinearEyeDepth (UNITY_SAMPLE_DEPTH(texProj));  
  110.                     // 获取投影纹理的Z  
  111.                     float partZ i.projPos.z;  
  112.                     // 限制在0到1  
  113.                     float fade saturate (_InvFade (sceneZ-partZ));  
  114.                     i.color.a *= fade;  
  115.                     //#endif  
  116.                     return 2.0f i.color _TintColor tex2D(_MainTex, i.texcoord);  
  117.                  
  118.                 ENDCG   
  119.              
  120.             
  121.       
  122.         // ---- Dual texture cards  
  123.         SubShader  
  124.             Pass  
  125.                 SetTexture [_MainTex]  
  126.                     constantColor [_TintColor]  
  127.                     combine constant primary  
  128.                  
  129.                 SetTexture [_MainTex]  
  130.                     combine texture previous DOUBLE  
  131.                  
  132.              
  133.          
  134.       
  135.         // ---- Single texture cards (does not do color tint)  
  136.         SubShader  
  137.             Pass  
  138.                 SetTexture [_MainTex]  
  139.                     combine texture primary  
  140.                  
  141.              
  142.          
  143.      

 

制作好特效后直接将prefab拖到界面上,进行测试:

  1. using UnityEngine;  
  2. using System.Collections;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using UnityEngine;  
  8.   
  9. public class TestLoadParticle: MonoBehaviour   
  10.  
  11.     public GameObject m_testParticle;  
  12.     public Transform m_listParent;  
  13.   
  14.     void Start()  
  15.      
  16.         UpdateList(1,1f);  
  17.         UpdateList(2,1f);  
  18.         UpdateList(3,1f);  
  19.         UpdateList(4,1f);  
  20.      
  21.   
  22.     public void UpdateList(int index, float size)  
  23.      
  24.         Transform item m_listParent.FindChild(index.ToString());  
  25.         LoadEffect(item, m_testParticle, size);  
  26.      
  27.   
  28.     public void LoadEffect(Transform parent, GameObject resObj, float size)  
  29.      
  30.         Transform item ((GameObject)GameObject.Instantiate(resObj)).transform;  
  31.         item.SetParent(parent);  
  32.         item.localPosition Vector3.zero;  
  33.         item.localEulerAngles Vector3.zero;  
  34.         item.localScale new Vector3(size, size, size);  
  35.         // 遍历子对象,使用新创建的材质球  
  36.         GetChildMaterial(item);  
  37.      
  38.   
  39.     private void GetChildMaterial(Transform parent)  
  40.      
  41.         foreach (Transform child in parent)  
  42.          
  43.             Renderer mat child.GetComponent();  
  44.             if (null != mat && null != mat.sharedMaterial)  
  45.              
  46.                 mat.sharedMaterial mat.renderer.material;  
  47.              
  48.             GetChildMaterial(child);  
  49.          
  50.      

使用mat.sharedMaterial mat.renderer.material;  用来避免特效共用同一个材质球的问题,这样就可以单独对特效进行缩放(为了统一规范,只能在挂有ParticleScale脚本的特效父节点进行缩放)。

以上这种方式在UGUI和NGUI上都可以。

 

参考来源:

http://forum.unity3d.com/threads/shocked-particle-emitter-not-scalable-solved.104817/

0 0
原创粉丝点击