uGUI の Image
は IMeshModifier
を利用すれば、頂点座標や uv の変更ができました
しかし、SpriteRenderer
では Sprite の頂点座標や uv を利用しているため変更ができません
そのため、Shader を利用して FillAmount を実装する必要があります
使い方
SpriteRenderer
がある GameObject に SpriteRendererFillAmount
を追加することで利用できます
値の変更は FillAmount
に直接値を代入することで変更できます
[SerializeField] private SpriteRendererFillAmount _spriteFill; private void Awake() { _spriteFill.FillAmount = 0.5f; }
shader の実装
難しい実装をする必要は無く、clip
を利用して _FillAmount の値に応じて描画しないように実装するだけです
一応反転して使えるように、_Reverse 時の処理も記述しています
clip( lerp( -i.uv.y + _FillAmount, i.uv.y - (1 - _FillAmount), _Reverse ) );
スクリプトの実装
SpriteRenderer
は sealed されているため、継承することができないため
パラメータを操作するコンポーネントを作成します
public sealed class SpriteRenderer : Renderer
material の差し替えが必要なため、runtime で Shader を取得してセットしています
マテリアルが通常と異なるため、バッチング対象外となる点は注意が必要です
var shader = Shader.Find("Hidden/SpriteRendererFillAmount"); _material = new Material(shader); _spriteRenderer.material = _material;
コード
using UnityEngine; [RequireComponent(typeof(SpriteRenderer))] public class SpriteRendererFillAmount : MonoBehaviour { [SerializeField, HideInInspector] private SpriteRenderer _spriteRenderer; [SerializeField, Range(0f, 1f)] private float _fillAmount = 1f; public float FillAmount { get { return _fillAmount; } set { _fillAmount = Mathf.Clamp01(value); if (_material != null) { _material.SetFloat(PropertyId, _fillAmount); } } } private void OnValidate() { FillAmount = _fillAmount; } private static readonly int PropertyId = Shader.PropertyToID("_FillAmount"); private Material _material; private void Reset() { _spriteRenderer = GetComponent<SpriteRenderer>(); } private void Awake() { var shader = Shader.Find("Hidden/SpriteRendererFillAmount"); if (shader == null) { Debug.LogWarning("Shader Not Found"); return; } _material = new Material(shader); //Material の差し替え _spriteRenderer.material = _material; FillAmount = _fillAmount; } }
シェーダー
Shader "Hidden/SpriteRendererFillAmount" { Properties { [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {} _FillAmount ("FillAmount", Range(0, 1)) = 0 [MaterialToggle] _Reverse ("Reverse", float) = 0 } SubShader { Tags { "RenderType"="Transparent" } Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float4 color: COLOR; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float4 color: COLOR; float2 uv : TEXCOORD0; }; sampler2D _MainTex; float _FillAmount; float _Reverse; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.color = v.color; return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv) * i.color; clip( lerp( -i.uv.y + _FillAmount, i.uv.y - (1 - _FillAmount), _Reverse ) ); return col; } ENDCG } } }