Unity5.4でモーダルダイアログもどきを作る

Unity の実行中にモーダルダイアログを出してみました。
![2016-08-18_144143.png](https://qiita-image-store.s3.amazonaws.com/0/46088/6f341a96-dc56-0d4e-5bea-31b57fcf7d5e.png)

編集中は UnityEditor の機能にあるようですが、実行中には標準では機能がないようです。

動作確認は、Unityエディタ上と Standalone(windows x86, x86_64) 版で行いました。
十分な検証はしていませんので、自己責任でご利用ください。
アドバイスなどありましたらコメントよろしくお願いします。

サンプルコードは、画面右上のゴミ箱の Sprite がクリックされたときに、全てのアイテムを削除してよいかをたずねるプログラムの抜粋です。

# モーダルじゃないモードレスダイアログを作る
下記の参照サイトの1に紹介されているとおり、まずはダイアログ用の Canvas を作ります。
すでに uGUI を使っている場合は Canvas があると思います。
それとは別にダイアログ専用の Canvas を作ります。

Canvas の子にはダイアログとして表示したい部品を追加します。
たとえば、メッセージ用の Text や選択用の Button を配置してください。
![2016-08-18_143241.png](https://qiita-image-store.s3.amazonaws.com/0/46088/bdd6c09d-c7c5-10a8-c08f-a06d1415fbf2.png)

ウィンドウ枠が欲しければ、メッセージやボタンのある場所にだけ Image を配置すると手軽にそれっぽくなります。
![2016-08-18_144728.png](https://qiita-image-store.s3.amazonaws.com/0/46088/132393f9-0e06-8d91-cd85-5e8047a0d3e1.png)

次にダイアログを利用するスクリプトを書きます。
今回はゴミ箱の絵の Sprite に次のスクリプトをコンポーネントとして追加しています。
スクリプト上では Canvas の有効性を操作します。
サンプルの Canvas の変数名は canvasConfirmAllHoshiDelete です。（長い。。。）

```csharp
using UnityEngine;
using System.Collections;

public class TrashBox : MonoBehaviour {

    // エディタのインスペクタで、この変数にヒエラルキーにある Canvas を割り当ててください。
    public Canvas canvasConfirmAllHoshiDelete = null;

    // Use this for initialization
    void Start() {
        // ダイアログを表示するときまで、 Canvas を無効にしておく。
        if (canvasConfirmAllHoshiDelete != null)
        {
            canvasConfirmAllHoshiDelete.enabled = false;
        }
    }

    // クリックされた
    void OnMouseUpAsButton()
    {
        confirmAllHoshiDelete();
    }

    // ダイアログを表示
    public void confirmAllHoshiDelete()
    {
        // Canvas を有効にする
        if (canvasConfirmAllHoshiDelete != null)
        {
            canvasConfirmAllHoshiDelete.enabled = true;
        }
    }

    // Yes ボタンと関連づけたイベントハンドラ関数
    public void onButtonYes()
    {
        // Canvas を無効にする。(ダイアログを閉じる)
        canvasConfirmAllHoshiDelete.enabled = false;

        // アイテムの削除処理(省略)
    }

    // No ボタンと関連づけたイベントハンドラ関数
    public void onButtonNo()
    {
        // Canvas を無効にする。(ダイアログを閉じる)
        canvasConfirmAllHoshiDelete.enabled = false;
    }
}
```

あとは、このコンポーネントにインスペクタ上でヒエラルキーのダイアログ用の Canvas を割り当てます。
![2016-08-18_142856.png](https://qiita-image-store.s3.amazonaws.com/0/46088/b54787c6-ad9e-bbe6-784d-5e57ec9478e4.png)


# モーダルダイアログにする
## uGUI オブジェクトはパネルを前面に置くことで無効にする。
さきほど作った Canvas に Panel を追加します。範囲はスクリーンと同じにします。
![2016-08-18_143726.png](https://qiita-image-store.s3.amazonaws.com/0/46088/1ed65869-4214-83e3-b147-39d2682324ff.png)

Panel がかぶさった場所のそれより奥の Button などの uGUI の操作が無効になります。

Panel の透過度と色は Color プロパティで変更できます。

### 編集中に Panel が邪魔な場合
![2016-08-18_145241.png](https://qiita-image-store.s3.amazonaws.com/0/46088/cd4e47d5-6420-84ea-359c-354c0455f55c.png)

編集中、後ろ側のオブジェクトを触れなくて邪魔な場合は、ダイアログ用の Canvas のインスペクタ上の左上のチェックボックスを一時的にオフにするとよかったです。
ただし、実行前はチェックを戻しておいてください。


## マウスイベントの無効化
これだけだと、 OnMouseDown などのマウスイベントを実装した GameObject は反応してしまいます。
そこで、反応してほしくないマウスイベントの最初に次のコードを追加します。

```csharp
if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
{
    return;
}
```

このコードにより uGUI のオブジェクトがこのオブジェクトの上にあった場合は return します。
さきほどの Panel も uGUI なので、その範囲内のすべてのオブジェクトのマウスイベントをキャンセルできます。

# 参考サイト
1. [【Unity】アプリケーションの終了を確認するダイアログを表示する - テラシュールブログ](http://tsubakit1.hateblo.jp/entry/2016/05/26/073000)
1. [UnityのuGUIでボタンと一緒に後ろのオブジェクトが押されないようにする - テラシュールブログ](http://tsubakit1.hateblo.jp/entry/2015/04/10/012238)