参考mask 实现一个基于shader,填充方式的进度条
mask源码地址: https://bitbucket.org/Unity-Technologies/ui/downloads/?tab=tags
Shader "UI/CP3"
{
Properties
{
[PerRendererData] _MainTex ("Texture", 2D) = "white" {}
[PerRendererData] _Width ("Width", Float) = 0
[PerRendererData] _Height ("Height", Float) = 0
_Color("Tint", Color) = (1,1,1,1)
_Progress ("Progress", Float) = 0
}
SubShader
{
Tags {
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
LOD 100
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 _Color;
float _Progress;
float _Width;
float _Height;
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
float px = (i.uv.x - 0.5) * _Width / _Height;
float py = (i.uv.y - 0.5);
float isPro = step(px * px + py * py, _Progress * _Progress);
return (col * isPro) + (col * _Color * col.a * !isPro);
}
ENDCG
}
}
}
//PointProgess.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.UI;
using UnityEngine.Serialization;
namespace VMUI
{
//添加到菜单
[AddComponentMenu("UI/PointProgress", 14)]
//总是执行
[ExecuteAlways]
//需要RectTransform组件
[RequireComponent(typeof(RectTransform))]
//不允许同时编辑
[DisallowMultipleComponent]
// ugui下的接口,用于更新ui
public class PointProgress : UIBehaviour, ICanvasRaycastFilter, IMaterialModifier
{
private static List m_List = new List();
[NonSerialized]
private RectTransform m_RectTransform;
public RectTransform rectTransform
{
get { return m_RectTransform ?? (m_RectTransform = GetComponent()); }
}
[NonSerialized]
private Material m_Material;
[SerializeField]
private int m_Progess = 0;
//每次改变进度值时,重新调用渲染绘制
public int Progess
{
get{return m_Progess;}
set
{
if(m_Progess == value)
return;
m_Progess = value;
if (graphic != null)
graphic.SetMaterialDirty();
}
}
//Graphic 渲染组件 无则说明不支持ugui渲染 不可调用相关方法
[NonSerialized]
private Graphic m_Graphic;
///
/// The graphic associated with the Mask.
///
public Graphic graphic
{
get { return m_Graphic ?? (m_Graphic = GetComponent()); }
}
protected override void OnEnable()
{
base.OnEnable();
if (graphic != null)
{
graphic.canvasRenderer.hasPopInstruction = true;
graphic.SetMaterialDirty();
}
}
protected override void OnDisable()
{
base.OnDisable();
if (graphic != null)
{
graphic.SetMaterialDirty();
graphic.canvasRenderer.hasPopInstruction = false;
graphic.canvasRenderer.popMaterialCount = 0;
}
//释放HideFlags.DontSave标志的资源
DestroyImmediate(m_Material);
m_Material = null;
}
//编辑器下的渲染相关回调
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
if (!IsActive())
return;
if (graphic != null)
graphic.SetMaterialDirty();
}
#endif
public virtual bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
if (!isActiveAndEnabled)
return true;
return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera);
}
//使用SetMaterialDirty后 会调用到该接口获取渲染材质
public virtual Material GetModifiedMaterial(Material baseMaterial)
{
//为每个物体创建材质,进度和颜色等 独立设置
if(m_Material == null){
//拷贝已有材质
m_Material = new Material(baseMaterial);
m_Material.name = m_Material.name + "(Copy)";
//HideFlags.DontSave | HideFlags.NotEditable
//HideFlags 使用 | 合并标签
//DontSave 资源需要DestroyImmediate释放,否则会一直存在内存中
//NotEditable 不可在编辑器中编辑资源
m_Material.hideFlags = HideFlags.DontSave;
//选择完材质后 需要设定宽高 方便计算与中心点的距离 见相关shader
m_Material.SetFloat("_Width", rectTransform.sizeDelta.x);
m_Material.SetFloat("_Height", rectTransform.sizeDelta.y);
}
//设置单独材质的进度
m_Material.SetFloat("_Progress", Progess / 100.0f);
return m_Material;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
//PointProgress类对应编辑器显示 PointProgressEditor.cs
namespace VMUI
{
[CustomEditor(typeof(PointProgress), true)]
[CanEditMultipleObjects]
public class PointProgressEditor : Editor
{
SerializedProperty m_Progess;
protected virtual void OnEnable()
{
m_Progess = serializedObject.FindProperty("m_Progess");
}
public override void OnInspectorGUI()
{
var graphic = (target as PointProgress).GetComponent();
if (graphic && !graphic.IsActive())
EditorGUILayout.HelpBox("Masking disabled due to Graphic component being disabled.", MessageType.Warning);
serializedObject.Update();
//进度条化 m_Progess
EditorGUILayout.IntSlider (m_Progess, 0, 100, new GUIContent (""), new GUILayoutOption[1]{GUILayout.Width(300)});
//更新serialized属性
serializedObject.ApplyModifiedProperties();
}
}
}
Graphic是UGUI的核心组件,负责显示图像。它是一个抽象类,是MaskableGraphic(可遮罩图像)的基类(同样是抽象类),而后者是RawImage、Image和Text的基类。
https://blog.csdn.net/ecidevilin/article/details/52548747