先看一下效果

C#脚本
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[DisallowMultipleComponent]
[RequireComponent(typeof(Image))]
[AddComponentMenu("UI/UISuperMask")]
public class UISuperMask :Mask
{
private float m_LastminX=-1f,m_LastminY=-1f,m_LastmaxX=-1f,m_LastmaxY=-1f;
private float m_MinX=0f,m_MinY=0f,m_MaxX=0f,m_MaxY=0f;
private Vector3[] m_Corners = new Vector3[4];
private Image m_Image;
void GetWorldCorners()
{
if(!Mathf.Approximately(m_LastminX,m_MinX) ||
!Mathf.Approximately(m_LastminY,m_MinY)||
!Mathf.Approximately(m_LastmaxX,m_MaxX)||
!Mathf.Approximately(m_LastmaxY,m_MaxY))
{
RectTransform rectTransform = transform as RectTransform;
rectTransform.GetWorldCorners (m_Corners);
m_LastminX = m_MinX;
m_LastminY = m_MinY;
m_LastmaxX = m_MaxX;
m_LastmaxY = m_MaxY;
m_MinX = m_Corners [0].x;
m_MinY = m_Corners [0].y;
m_MaxX = m_Corners [2].x;
m_MaxY = m_Corners [2].y;
Debug.LogFormat("MinX:{0},MaxX:{1},MinY:{2},MaxY:{3}",m_MinX,m_MaxX,m_MinY,m_MaxY);
}
}
protected override void OnRectTransformDimensionsChange ()
{
base.OnRectTransformDimensionsChange ();
Refresh ();
}
public void Refresh()
{
GetWorldCorners ();
if(Application.isPlaying)
{
foreach( ParticleSystemRenderer system in transform.GetComponentsInChildren<ParticleSystemRenderer>(true))
{
SetRenderer(system);
}
}
}
void SetRenderer(Renderer renderer)
{
if (renderer.sharedMaterial) {
Shader shader = Resources.Load<Shader> ("Alpha Blended Premultiply");
renderer.material.shader = shader;
Material m = renderer.material;
m.SetFloat("_MinX",m_MinX);
m.SetFloat("_MinY",m_MinY);
m.SetFloat("_MaxX",m_MaxX);
m.SetFloat("_MaxY",m_MaxY);
}
}
}
Shader脚本
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "UI/Mask/Particles/Alpha Blended Premultiply" {
Properties {
_MainTex ("Particle Texture", 2D) = "white" {}
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
//-------------------add----------------------
_MinX ("Min X", Float) = -10
_MaxX ("Max X", Float) = 10
_MinY ("Min Y", Float) = -10
_MaxY ("Max Y", Float) = 10
//-------------------add----------------------
}
Category {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend One OneMinusSrcAlpha
ColorMask RGB
Cull Off Lighting Off ZWrite Off
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#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 : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
#ifdef SOFTPARTICLES_ON
float4 projPos : TEXCOORD1;
#endif
//-------------------add----------------------
float3 vpos : TEXCOORD2;
//-------------------add----------------------
};
float4 _MainTex_ST;
//-------------------add----------------------
float _MinX;
float _MaxX;
float _MinY;
float _MaxY;
//-------------------add----------------------
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#ifdef SOFTPARTICLES_ON
o.projPos = ComputeScreenPos (o.vertex);
COMPUTE_EYEDEPTH(o.projPos.z);
#endif
//-------------------add----------------------
o.vpos = v.vertex.xyz;
//-------------------add----------------------
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
sampler2D_float _CameraDepthTexture;
float _InvFade;
fixed4 frag (v2f i) : SV_Target
{
#ifdef SOFTPARTICLES_ON
float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
float partZ = i.projPos.z;
float fade = saturate (_InvFade * (sceneZ-partZ));
i.color.a *= fade;
#endif
fixed4 col = i.color * tex2D(_MainTex, i.texcoord) * i.color.a;
//-------------------add----------------------
col.a *= (i.vpos.x >= _MinX );
col.a *= (i.vpos.x <= _MaxX);
col.a *= (i.vpos.y >= _MinY);
col.a *= (i.vpos.y <= _MaxY);
col.rgb *= col.a;
//-------------------add----------------------
return col;
}
ENDCG
}
}
}
}
本篇内容主要引自雨松的unity3d游戏开发,,在此记录一下

本文介绍了一种使用Unity3D实现UI遮罩的方法,通过编写C#脚本和Shader来限定粒子系统的显示区域。具体包括:创建自定义UI组件UISuperMask,通过获取世界坐标来更新遮罩范围,并在Shader中对粒子系统的透明度进行裁剪。
1622

被折叠的 条评论
为什么被折叠?



