UGUI(九)UI粒子特效
来源:互联网 发布:网络言情经典小说作家 编辑:程序博客网 时间:2024/05/19 18:14
我们工作中使用的次时代界面NGUI,UGUI,在游戏窗口大小发生变化的时候,细心观察界面元素它的大小并没有变化(这个大小相对于电脑屏幕)。
但是3D场景中的模型大小是变化的,而粒子也一样会发生变化,如果我们想在UI上使用系统自带的粒子系统,这样就无法兼容各种大小的游戏窗口,因为无法使用系统粒子,就只能采用序列图或者摄像机渲染纹理的方式去做特效,这样做不是不可以,但是前者资源量大,后者不好管理。
那么我们能不能做到把粒子系统做的特效保持固定的大小呢?其实是可以的,在屏幕大小发生变化的时候,重新计算粒子顶点的缩放,保持它的大小不变,这样就可以和UI保持一致。
看下图,粒子和界面元素在同一层级,屏幕大小发生变化的时候,粒子也不会变化:
制作环境:
1.在UI层的Canvas下。
2.给特效父节点挂上ParticleScale脚本(传人一些参数到材质球中)。
3.粒子shader使用UI_Particles/Alpha Blended(根据官方shader修改而来)。
4.粒子的渲染模式RenderMode选为Mesh。
ParticleScale脚本如下:
- using
UnityEngine; - using
System.Collections; - using
System; - using
System.Collections.Generic; - using
System.Linq; - using
System.Text; - using
UnityEngine; -
- ///
- ///
添加到UI层粒子的父节点 - ///
适用于UGUI,NGUI - ///
- [ExecuteInEditMode]
- public
class ParticleScale : MonoBehaviour - {
-
private Transform m_transform; -
private List newm_matList = List(); -
private Camera m_uiCamera; -
-
void Start() -
{ -
m_transform = transform; -
m_matList.Clear(); -
GetChildMaterial(m_transform, ref m_matList); -
-
m_uiCamera = GameObject.Find("ui_camera").GetComponent(); -
-
MeshRenderer mr = m_transform.GetComponent(); -
if ( null== mr)m_transform.gameObject.AddComponent(); -
} -
-
private void GetChildMaterial(Transform parent, ref List list) -
{ -
foreach (Transform child in parent) -
{ -
Renderer mat = child.GetComponent(); -
if ( null!= nullmat && != mat.sharedMaterial) -
{ -
list.Add(mat.sharedMaterial); -
} -
GetChildMaterial(child, ref list); -
} -
} -
-
public void OnWillRenderObject() -
{ -
if (m_matList.Count 0)== Start(); -
foreach (Material item in m_matList) -
{ -
item.SetVector("_Center", m_transform.position); -
item.SetVector("_Scaling", m_transform.lossyScale); -
item.SetMatrix("_Camera", m_uiCamera.worldToCameraMatrix); -
item.SetMatrix("_CameraInv", m_uiCamera.worldToCameraMatrix.inverse); -
} -
} - }
UI_Particles/Alpha Blended代码如下:
- Shader
"UI_Particles/Alpha Blended" { -
Properties { -
_TintColor ("Tint Color" ,Color) 0.5,0.5,0.5,0.5)= ( -
_MainTex ("Particle Texture" ,2D) "white"= {} -
_InvFade ("Soft Particles ,Factor" Range( 0.01,3.0))= 1.0 -
} -
-
Category { -
Tags -
{ -
"Queue"="Transparent" -
"IgnoreProjector"="True" -
"RenderType"="Transparent" -
} -
// 源rgb*a + 背景rgb*(1-源a) -
Blend SrcAlpha OneMinusSrcAlpha -
// 显示透明度大于0.01的 -
AlphaTest Greater .01 -
ColorMask RGB -
// 不裁剪前后 -
Cull Off -
Lighting Off -
// 关闭深度缓存,作为面片显示的特效不需要缓存深度 -
ZWrite Off -
// 指定顶点数据源映射到目标硬件 -
BindChannels { -
Bind "Color", color -
Bind "Vertex", vertex -
Bind "TexCoord", texcoord -
} -
-
SubShader { -
Pass { -
-
CGPROGRAM -
#pragma vertex vert -
#pragma fragment frag -
#pragma fragmentoption ARB_precision_hint_fastest -
#pragma multi_compile_particles -
-
#include "UnityCG.cginc" -
-
sampler2D _MainTex; -
fixed4 _TintColor; -
-
struct appdata_t { -
float4 vertex : POSITION; -
fixed4 color : COLOR; -
float2 texcoord : TEXCOORD0; -
}; -
-
struct v2f { -
float4 vertex : POSITION; -
fixed4 color : COLOR; -
float2 texcoord : TEXCOORD0; -
// 开启软边粒子时,需要用到投影纹理 -
#ifdef SOFTPARTICLES_ON -
float4 projPos : TEXCOORD1; -
#endif -
}; -
-
float4 _MainTex_ST; -
float3 _Scaling; -
float4 _Center; -
float4x4 _Camera; -
float4x4 _CameraInv; -
-
v2f vert (appdata_t v) -
{ -
v2f o; -
if(_Scaling.x != 0) -
{ -
//【摄像机空间】转到【世界空间】 -
float4 objV = mul(_CameraInv, v.vertex); -
// 控制顶点中心点 -
objV.xyz -= _Center; -
// 控制顶点缩放,当屏幕大小发生改变的时,根据lossyScale来计算新的顶点 -
objV.xyz = float3(_Scaling.x * objV.x, _Scaling.y * objV.y, _Scaling.z * objV.z); -
// 控制顶点中心点 -
objV.xyz += _Center; -
// 【世界坐标】转到【摄像机坐标】 -
o.vertex = mul(_Camera, objV); -
// END OF CHANGE -
o.vertex = mul(UNITY_MATRIX_MVP, o.vertex); -
}else{ -
// 官方shader直接运行这里 -
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); -
} -
#ifdef SOFTPARTICLES_ON -
// 计算顶点在屏幕的纹理 -
o.projPos = ComputeScreenPos (o.vertex); -
COMPUTE_EYEDEPTH(o.projPos.z); -
#endif -
o.color = v.color; -
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex); -
return o; -
} -
-
sampler2D _CameraDepthTexture; -
float _InvFade; -
-
fixed4 frag (v2f i) : COLOR -
{ -
// 开启软边粒子时,会根据场景的深度调整粒子的透明度,确保无黑线 -
#ifdef SOFTPARTICLES_ON -
// 对摄像机深度图进行采样 -
float4 texProj = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)); -
// 【Z深度缓存信息】转为【场景线性深度】 -
float sceneZ = LinearEyeDepth (UNITY_SAMPLE_DEPTH(texProj)); -
// 获取投影纹理的Z -
float partZ = i.projPos.z; -
// 限制在0到1 -
float fade = saturate (_InvFade * (sceneZ-partZ)); -
i.color.a *= fade; -
//#endif -
return 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord); -
} -
ENDCG -
} -
} -
-
// ---- Dual texture cards -
SubShader { -
Pass { -
SetTexture [_MainTex] { -
constantColor [_TintColor] -
combine constant * primary -
} -
SetTexture [_MainTex] { -
combine texture * previous DOUBLE -
} -
} -
} -
-
// ---- Single texture cards (does not do color tint) -
SubShader { -
Pass { -
SetTexture [_MainTex] { -
combine texture * primary -
} -
} -
} -
} - }
制作好特效后直接将prefab拖到界面上,进行测试:
- using
UnityEngine; - using
System.Collections; - using
System; - using
System.Collections.Generic; - using
System.Linq; - using
System.Text; - using
UnityEngine; -
- public
class TestLoadParticle: MonoBehaviour - {
-
public GameObject m_testParticle; -
public Transform m_listParent; -
-
void Start() -
{ -
UpdateList(1,1f); -
UpdateList(2,1f); -
UpdateList(3,1f); -
UpdateList(4,1f); -
} -
-
public void UpdateList( intindex, floatsize) -
{ -
Transform item = m_listParent.FindChild(index.ToString()); -
LoadEffect(item, m_testParticle, size); -
} -
-
public void LoadEffect(Transform floatparent, GameObject resObj, size) -
{ -
Transform item = ((GameObject)GameObject.Instantiate(resObj)).transform; -
item.SetParent(parent); -
item.localPosition = Vector3.zero; -
item.localEulerAngles = Vector3.zero; -
item.localScale = new Vector3(size, size, size); -
// 遍历子对象,使用新创建的材质球 -
GetChildMaterial(item); -
} -
-
private void GetChildMaterial(Transform parent) -
{ -
foreach (Transform child in parent) -
{ -
Renderer mat = child.GetComponent(); -
if ( null!= nullmat && != mat.sharedMaterial) -
{ -
mat.sharedMaterial = mat.renderer.material; -
} -
GetChildMaterial(child); -
} -
} - }
使用mat.sharedMaterial
以上这种方式在UGUI和NGUI上都可以。
参考来源:
http://forum.unity3d.com/threads/shocked-particle-emitter-not-scalable-solved.104817/
- UGUI(九)UI粒子特效
- UGUI研究院之UI粒子特效自适应缩放(二十二)
- UGUI研究院之UI粒子特效自适应缩放(二十二)
- UGUI如何在UI与UI直接穿插粒子特效和模型
- UGUI-UI添加特效
- Cocos2dx 小技巧(九)现成的粒子特效
- Cocos2dx 小技巧(九)现成的粒子特效
- Cocos2dx 小技巧(九)现成的粒子特效
- Cocos2dx 小技巧(九)现成的粒子特效
- unity UGUI与模型混合显示(ui显示特效)
- Unity5.3+ 在UGUI 上使用 粒子特效
- UGUI中让粒子特效穿插在两个界面之间
- ui的粒子特效的层级问题
- Silverlight 2.5D RPG游戏技巧与特效处理:(九)粒子系统
- Silverlight 2.5D RPG游戏技巧与特效处理:(九)粒子系统
- Unity之一天一个技术点(十)---UI添加粒子特效
- 粒子特效
- 粒子特效
- iOS MDM开发流程
- 为什么析构函数是虚函数
- Java中的抽象类和接口
- 从编译器角度分析C语言中数组名和指针的区别
- strcpy没有声明 c++头文件详解
- UGUI(九)UI粒子特效
- OpenCV入门笔记(六) 形态学变换
- PullToRefreshListView进阶(一)----->下拉刷新
- 关于电话面试的粗略回忆
- Apple iOS MDM service 簡介
- poi XSSFWorkbook实现excel中的下拉框
- Deep Learning(深度学习)学习笔记整理系列之(七)
- AndroidManifest中activity属性参数设置大全
- Delegate的使用场合