UnityのMaskがなんかジャギジャギになっちゃうときの対処法

## はじめに
皆さんはUnityのMaskコンポーネントを使ったことがありますか？
今回Maskを利用して画像を好きな形にマスクしようとしたらおかしなことになっちゃったので、解決方法とそれに関する調査についてまとめました！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/e7f02cd6-6695-9a64-7901-a11fd9223248.png" width="350">

## 環境
macOS Sonoma
Unity 2021.3.29f1

## 解決法
- Unityのバージョンを上げる！ (2022.3.42f1では問題なく動きました)
- Maskコンポーネントがついたテクスチャのアルファを 1 にする

## 起こったこと
画像のように、ボタンを好きな形に切り抜くためMaskコンポーネントを利用したところ、輪郭がぼやけておかしな状況になってしまいました。

↓マスクとして利用した画像と実際マスクされた結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/cbf6f16c-960f-d9cc-3226-2a1a17657f42.png" width="250"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/e7f02cd6-6695-9a64-7901-a11fd9223248.png" width="270">

## 解決？
ひとまずネットで有識者を探したところ、このような議論を見かけました！

https://discussions.unity.com/t/smooth-sprite-mask-for-ui/795046

端的にいうと **Mask側のImageのアルファを1にしたらいい** とのこと。半信半疑でやってみると本当に治りました！！
でもなぜ？？

## Maskコンポーネントを見てみる
手がかりを得るため、Maskがついているオブジェクトのインスペクタを見てみました。
UI/Default シェーダーのプロパティに値が設定されているようです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/b116345b-7b88-3a9d-20bb-ddeba140516d.png" width="400">

おそらくステンシルマスクによってその機能が実現されていると予想し、実際にシェーダーの中身を見てみました。

## UI/Defaultシェーダーを見てみる
ビルトインシェーダーをダウンロードしてUI/Defaultシェーダーを見てみると、frag関数内にこちらのような記述がありました。

```
#ifdef UNITY_UI_ALPHACLIP
    clip (color.a - 0.001);
#endif
```

このあたりをみると、アルファが0.001より小さいところでは描画がスキップされるとわかります。

どうやらマスクする側の画像の十分アルファが小さい部分についてはステンシルバッファへの書き込みがスキップされる仕組みになっているようです。

Mask側のImageのアルファを小さくするとマスクがうまくいったのはこれが理由だったみたいです。
同様の理屈で、シェーダー内の0.001の部分の値を大きくすることでもうまくマスクできることが確認できました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/a53c07c6-826c-6130-8437-bf268832c96e.png" width="300">


逆にいうとマスクがうまくいかなかった時は、透明なはずの場所でアルファが0.001より大きい値を持っていたということになります。

Image内のカラーを小さくすることでマスクがうまくいったのは、それらのアルファ値が十分小さくなり、ステンシルバッファへの書き込みが行われなくなったからのようです。
<br>

しかし、なぜ透明なはずの場所にアルファ値が設定されていたんでしょうか？

## 画像データを調べる
画像データについて調べるため、アルファ値が 0.001 ~ 0.01 の部分が1になるようにPythonで処理し、グレースケールで表示してみました。その結果以下のようになり、画像ファイル自体には問題がなさそうだとわかりました。

↓特に輪郭に問題はなかった
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/9e566dc8-21d1-3741-0cb7-c726227f4339.png" width="300">

ということはUnity側でインポートする際に問題が起きているのでは...？ということでインポート設定を見てみました。

## テクスチャのインポート設定を見てみる!

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887533/c2006030-10c8-52e1-6a06-0290f55e67cf.png" width="300">

結論、Alpha Is Transparency の設定を外してみるとマスクがうまくいきました。
Alpha Is Transparency とはなんのための設定なんでしょうか？

同じバージョンのUnity公式のマニュアルを見てみると、
> Enable this property to dilate the color and avoid filtering artifacts on the edges if the alpha channel you specify is Transparency.	

とありました。

↓ 該当箇所
https://docs.unity3d.com/2021.3/Documentation/Manual/class-TextureImporter.html#AlphaTrans

**どゆこと？？**

ひとまず、フィルタリングの際にアーティファクトが生じないよう、エッジの部分に加工を施すような設定だというように認識しました。ここで周囲にアルファ値が設定されているっぽい気配がします。


## Unityのバージョンを変えたら動いた
新しいバージョンではこちらの処理が変更されているようで、2022.3.42f1 では特に何もせずともマスクがうまくいくようになっていました。
多分インポート時の処理がアップデートで変更されたのでは？と予想しています。
なんにせよこれからはできるだけ新しいバージョンを使おう！と決意...


## まとめ
マスクがうまくいかない現象について調べてみました。
結果、
- Maskはアルファテストとステンシルテストを利用して実装されていること
- テクスチャのインポート設定でアルファ値が周囲に設定されていたこと
- できるだけ最新バージョンを利用した方がいいこと

がわかりました。

間違っているところなどがあればぜひご指摘お待ちしております！