うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】Image で反射しているような表現をする

床に写ったような表現をさくっとできるコンポーネントを作成しました

現状一番下を0にしてもうっすらとは見えてしまうので、見えてしまう最大範囲を変える場合は対応が必要になります

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
[RequireComponent(typeof(Image))]
public class ReflectionImage : BaseMeshEffect
{
    [SerializeField]
    private Vector2 _shift = Vector2.zero;
    [SerializeField]
    [Range(0, 1f)]
    private float _alphaTop = 1f;
    
    [SerializeField]
    [Range(0, 1f)]
    private float _alphaBottom = 0.5f;
     
    private readonly List<UIVertex> _vertexList = new List<UIVertex>();
 
#if UNITY_EDITOR
    protected override void OnValidate()
    {
        _alphaTop = Mathf.Max(_alphaTop, _alphaBottom);
        base.OnValidate();
    }
#endif
 
    public override void ModifyMesh(VertexHelper helper)
    {
        _vertexList.Clear();
        helper.GetUIVertexStream(_vertexList);
        var min = _vertexList[0].uv0.y;
        var max = _vertexList[0].uv0.y;
 
        var count = _vertexList.Count;
         
        for (var i = 1; i < count; i++)
        {
            var uv = _vertexList[i].uv0;
            if (min > uv.y)
                min = uv.y;
            if (max < uv.y)
                max = uv.y;
        }
 
        var alphaTop = (byte)(255 * _alphaTop); 
        var alphaBottom = (byte)(255 * _alphaBottom); 
        
        for (var i = 0; i < count; i++)
        {
            var vertex = _vertexList[i * 2];
            vertex.position.x += _shift.x;
            vertex.position.y += _shift.y;
 
            var uv = vertex.uv0;
            
            var t = Mathf.InverseLerp(min, max, uv.y);
            uv.y = Mathf.Lerp(max, min, t);
            vertex.uv0 = uv;
            
            var color = vertex.color; 
            color.a = (byte)Mathf.Lerp(alphaBottom, alphaTop, t);
            vertex.color = color;
            _vertexList.Insert(i, vertex);
        }
        
        helper.Clear();
        helper.AddUIVertexTriangleStream(_vertexList);
    }
}