【Unity】Sprite Atlas に追加した白塗り画像の端を透けないようにする方法


# 背景

uGUI の Image で Source Image を None にすると白の塗りつぶし画像になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/d41765d2-444f-9bad-028e-632c142747d1.png)

一見白塗り画像として使えそうに見えますが、実はこれは Unity が None を UnityWhite というテクスチャに差し替えている状態です（Frame Debugger で確認できます）。
もしこのまま Sprite Atlas を利用すると、テクスチャが交互に使われて Batch 数がかさんでしまいます。
Sprite Atlas に白塗り画像を用意して利用すれば解決しますが、Fillter Mode を Point 以外にするとフチが透けてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/1c1e5518-294b-c26d-6338-565fc0b4e46d.png)

そこで今回は、Sprite Atlas に用意した白塗り画像の辺を透けさせない設定を紹介します。

# 設定方法

1. 用意した白埋め画像の Sprite Editor を開き、Border を全て 1 に設定
2. 白埋めしたい Image の Source Image に白埋め画像を指定
3. Image Type を Sliced に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/13408327-5159-2f7d-7979-b0ff910c9ad3.png)

もし高解像度モニターで端が透けたら、Pixels Per Unit の桁を増やしてみてください。

# 問題 : Image Type の Filled が使えない

紹介した方法は Image Type の Sliced 固定が必要なので Filled を利用できません。
ということで、Slider で先の白塗り画像を利用できるコンポーネントを作りました。
ご自由にご利用ください。不具合や改善点があれば連絡をお願いします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/129e8e7b-31af-e218-14ea-013748cb5612.png)

``` SliderFillImage.cs
using UnityEngine;
using UnityEngine.UI;

[ExecuteAlways]
public class SliderFillImage : MonoBehaviour
{
    [SerializeField] private Slider slider;
    [SerializeField] private RectTransform backGroundRectTransform;
    [SerializeField] private RectTransform fillRectTransform;
    [SerializeField] private float offsetWidth;

    private void Start()
    {
        slider.onValueChanged.AddListener(UpdateImageSize);
    }

    private void UpdateImageSize(float value)
    {
        var rate = Mathf.LerpUnclamped(slider.minValue, slider.maxValue, value);

        switch (slider.direction)
        {
            default:
            case Slider.Direction.LeftToRight:
            case Slider.Direction.RightToLeft:
                fillRectTransform.sizeDelta = new Vector2(
                    (backGroundRectTransform.rect.size.x + offsetWidth) * rate,
                    backGroundRectTransform.rect.size.y);
                break;
            case Slider.Direction.BottomToTop:
            case Slider.Direction.TopToBottom:
                fillRectTransform.sizeDelta = new Vector2(
                    backGroundRectTransform.rect.size.x,
                    (backGroundRectTransform.rect.size.y + offsetWidth) * rate);
                break;
        }
    }

#if UNITY_EDITOR
    private void Update()
    {
        if (Application.isPlaying) return;
        if (slider == null) return;
        if (backGroundRectTransform == null) return;
        if (fillRectTransform == null) return;

        Vector2 pivot, anchorMin, anchorMax;
        switch (slider.direction)
        {
            default:
            case Slider.Direction.LeftToRight:
                pivot = new Vector2(0.0f, -0.5f);
                anchorMin = new Vector2(0.0f, 0.5f);
                anchorMax = new Vector2(0.0f, 0.5f);
                break;
            case Slider.Direction.RightToLeft:
                pivot = new Vector2(1.0f, 0.5f);
                anchorMin = new Vector2(1.0f, 0.5f);
                anchorMax = new Vector2(1.0f, 0.5f);
                break;
            case Slider.Direction.BottomToTop:
                pivot = new Vector2(-0.5f, 0.0f);
                anchorMin = new Vector2(0.5f, 0.0f);
                anchorMax = new Vector2(0.5f, 0.0f);
                break;
            case Slider.Direction.TopToBottom:
                pivot = new Vector2(0.5f, 1.0f);
                anchorMin = new Vector2(0.5f, 1.0f);
                anchorMax = new Vector2(0.5f, 1.0f);
                break;
        }

        fillRectTransform.pivot = pivot;
        fillRectTransform.anchorMin = anchorMin;
        fillRectTransform.anchorMax = anchorMax;

        UpdateImageSize(slider.value);
    }
#endif
}

```