透過画像を使ったボタンの範囲から透過されている部分を削除する

問題

Unityのボタンに円形の画像を使った際、ボタンの選択範囲が四角になってしまうため、円形の外にも選択判定ができてしまう問題があった。 単純な円形なら後述するICanvasRaycastFilterを使えばいけるけど、半円やキャラクタの形をしたボタンなどを実装したい場合は厳しそう。

例えば、下の星の画像でボタンを作り、星の範囲だけに判定をもたせたいのに、 f:id:ryu955:20180219235305p:plain:w200

こんな感じに、画像がちょうど入る四角い範囲がボタンになってしまい、ピンク色のところにも判定ができてしまう。

f:id:ryu955:20180219235437j:plain:w200

前提

  • 画像の非選択にしたい場所が透過されている
    • ようは透過画像を使いたい

デモ

処理の説明の前にとりあえずデモ。 左が処理前、右が処理後です。 処理前は星の外をクリックしても反応していますが、処理後は反応しなくなりました。

https://gyazo.com/4b83e6eca9a43d85af5299f75a64f52d

解決方法

RaycastMask.csをProjectにコピペ

github.com

f:id:ryu955:20180220000511p:plain

RaycastMask.csをProjectに置く。 また、コピペする際、25,122行目のフラグがあると動かないのでそれを除いたものをする。

Projectにある使いたい画像の設定を変える

f:id:ryu955:20180220000728p:plain

ボタンを作る

f:id:ryu955:20180220001246p:plain

おわり

ちょっと解説

RaycastMask.csのざっくりとした処理

  1. 画像の情報を取り、透過されているかを判定する(GetPixcel)
  2. 透過されていない範囲にレイキャストを与える(ICanvasRaycastFilter)

GetPixcel とは

座標(x, y)のピクセルのカラーを取得します。Unity - スクリプトリファレンス: Texture2D.GetPixel

これで画像の状態を取ることができる。

ICanvasRaycastFilter とは

RaycastMask.cs が継承してるクラス。

この要素はレイキャストをフィルタリングすることができます。トップレベルの要素がヒットした場合、その位置が有効であるとさらに 'チェック' することができます。 ICanvasRaycastFilter - Unity スクリプトリファレンス

これを使うことで、uGUIの選択範囲を広めたり狭めたりできる。 詳しい使い方は以下のサイトをみればわかると思います。

tsubakit1.hateblo.jp

Read/Write Enabled とは

テクスチャデータをスクリプトからアクセスできるようにします(GetPixels、SetPixels、その他の Texture2D 関数)。注意することとして、作成されたテクスチャデータは、テクスチャアセットとして必要なメモリ量は倍となります。必ず、必要な場合のみ使用してください。これは非圧縮や DXT 圧縮のテクスチャでのみ有効であり、その他の圧縮テクスチャの種類では読みこむことができません。デフォルトでは無効となっています。  テクスチャ - Unity マニュアル

これの設定がされてないと、RaycastMaskがGetPixcelで画像情報をとれないからチェックを入れないとダメだよってことですね。