UnityでNavigation Drawerっぽいものを作りました

# はじめに
こんにちは。Livesense Advent Calendar 7日目です。
普段はAndroidアプリの開発・運用を担当している私ですが、クロスプラットフォームにも最近興味が出てきました。
今回は少しだけ触ったことがあるUnityを駆使して、スマホアプリのNavigation Drawerっぽいものを作ってみたのでその紹介をさせてください！
本記事では初心者向けの記事となりますので、どうぞよろしくお願いいたします。

# Navigation Drawer
一般的にアプリの左側から出てくるメニューのことです。
別カテゴリーの画面に切り替える時や、アプリの設定画面を探すときに開くことが多いのではないでしょうか。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/58854658-1340-3085-0d35-2eefe1844050.png">
画像は[Material Design](https://material.io/components/navigation-drawer)より引用


# Unityで作るにあたって
UnityにはAndroidのようにNavigation Drawerを作るためのライブラリはありません~~（あったらすみません）~~。
そのため自前で作るか、有志の開発したassetを購入する必要があります。
今回はもちろん自前で実装してみます。

# 実装
## 1. プロジェクト作成
今回は3D要素はないので、Mobile 2Dで作成します。
<br><img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/b1c9a532-f421-17ca-5b04-b0ace630d9ef.png">

## 2. 画面準備
1. `「GameObject > UI > Canvas」` でHierarchyにCanvasを追加
2. Hierarchyの中にあるCanvasを右クリックし、`「UI > Panel」`を追加
3. PanelのInspectorから`Color`をクリックし、透明度(A)を255にする。色は任意
4. Panelを右クリックし、`「UI > Text」`と`「UI > Button」`を追加
<dt>Text設定値</dt>
<dd>Width : 500</dd>
<dd>Height : 200</dd>
<dd>FontSize : 100</dd>
<dd>Text : HOME</dd>
<dt>Button設定値</dt>
<dd>Anchor Presets : Top-Left</dd>
<dd>PosX : 150</dd>
<dd>PosY : -150</dd>
<dd>Width : 300</dd>
<dd>Height : 300</dd>
<dd>FontSize : 100</dd>
<dd>Text : ≡　(アイコンなのでテキストでなくてもOK)</dd>
5. Panelをコピペして、「Panel(1)」を生成
6. Panel(1) とTextとButtonをの設定値を一部変更
<dt>Panel(1)設定値</dt>
<dd>Color : Panel とは違う色にする</dd>
<dd>Anchor Presets : Bottom-Left</dd>
<dd>PosX : -980</dd>
<dd>PosY : 0</dd>
<dd>Width : 980</dd>
<dt>Text設定値</dt>
<dd>Text : SETTING</dd>
<dt>Button設定値</dt>
<dd>Text : ←　(アイコンなのでテキストでなくてもOK)</dd>
7. 2つのPanelの名前をそれぞれ以下の通りにする
<dd>Panel : HomePanel</dd>
<dd>Panel(1) : SettingPanel</dd>
8. 2つのButtonの名前をそれぞれ以下の通りにする
<dd>HomePanel配下のButton : NavigationButton</dd>
<dd>SettingPanel配下のButton : BackButton</dd>


HierarchyとSceneが以下の通りになっていることを確認して、問題なければ次へ進みます。

|Hierarchy|Scene|
|---|---|
|<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/05a3015a-3082-b87d-fd4b-25f49d7d745b.png">|<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/a5f82e19-ebfa-e5fa-406c-c270eb1be7a3.png">|


## 3. 画面切り替え用のスクリプト
1. ProjectタブのAssetsで右クリックし、`「Create → C# Script」`を選択
2. もう一度Assetsで右クリックし、`「Create → C# Script」`を選択
3. ファイル（クラス名）をそれぞれ`HomeDrawerNavigator`、`SettingDrawerNavigator`にリネーム
4. 以下のソースコードをそれぞれのクラスにコピペ

```HomeDrawerNavigator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class HomeDrawerNavigator : MonoBehaviour
{
    [SerializeField]
    GameObject settingPanel;

    public void OnClick()
    {
      // settingPanelのPositionを(0, 0)に移動
      if (settingPanel != null)
      settingPanel.transform.position = new Vector2(0, 0);
    }
}
```
```SettingDrawerNavigator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SettingDrawerNavigator : MonoBehaviour
{
    [SerializeField]
    GameObject settingPanel;

    public void OnClick()
    {
      // settingPanelのPositionを(-980, 0)に移動
      if (settingPanel != null)
      settingPanel.transform.position = new Vector2(-980, 0);
    }
}
```

## 4. スクリプト適用
1. `HomeDrawerNavigator.cs`を`NavigationButton`までドラッグ＆ドロップ
2. `NavigationButton`のInspectorにある`Home Drawer Navigator(Script)`の中にある、Setting Panelに`SettingPanel`を適用
<br><img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/2881d6db-148b-780d-519a-214bc353cd11.png">
3. `Home Drawer Navigator(Script)`の上にある、`On Click()`欄の右下にある「＋」をクリック
4. `None (Object)`の欄には`NavigationButton`を適用
5. `「No Function　> HomeDrawerNavigator > OnClick()`を選択
<br><img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/53f61b18-8ec2-93b6-b9a5-fcd17d0a9f67.png">
6. `SettingDrawerNavigator.cs`を`BackButton`までドラッグ&ドロップ
7. `BackButton`についても、上の2~5にそって同じように適用

## 5. 実行
Sceneの上にあるRun「▶︎」をクリックして動作確認してみましょう。
左上のButtonをクリックして以下のようになればOKです。

|起動直後・BackButtonクリック後|NavigationButtonクリック後|
|---|---|
|<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/aea41f0c-e28c-b408-6a73-434c67146856.png">|<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259412/8098e1a0-8ce8-47f3-5c53-fb82d67ec888.png">|

# おわりに
今回はNavigation Drawerっぽいものを紹介させていただきました。
Unityはゲーム開発の側面に目を向けがちですが、個人的にはクロスプラットフォームであることを生かしたスマホアプリ開発ができることが強みだと思っています。
Navigation Drawerの表示にスクリプトを用いましたが、ループ処理を使って徐々にPositionをずらすことでアニメーションのような動きもできます。
AndroidもiOSも両方作ってみたいけど...という方へぜひ参考になれば嬉しいです。

# 追記
それぞれのスクリプトを以下のように置き換えるとNavigation Drawerを開くアニメーションっぽいものができました。

```HomeDrawerNavigator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class HomeDrawerNavigator : MonoBehaviour
{
    [SerializeField]
    GameObject settingPanel;

    private bool isClicked = false;

    void Update() {
      if (isClicked && settingPanel != null) {
        settingPanel.transform.position = Vector2.MoveTowards(settingPanel.transform.position, new Vector2(0, 0), 3000f * Time.deltaTime);
      }

      if (settingPanel.transform.position.x == 0) {
        isClicked = false;
      }
    }

    public void OnClick()
    {
      isClicked = true;
    }
}
```
```SettingDrawerNavigator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SettingDrawerNavigator : MonoBehaviour
{
    [SerializeField]
    GameObject settingPanel;

    private bool isClicked = false;

    void Update() {
      if (isClicked && settingPanel != null) {
        settingPanel.transform.position = Vector2.MoveTowards(settingPanel.transform.position, new Vector2(-980, 0), 3000f * Time.deltaTime);
      }

      if (settingPanel.transform.position.x == -980) {
        isClicked = false;
      }
    }

    public void OnClick()
    {
      isClicked = true;
    }
}
```

# 参考
- https://material.io/components/navigation-drawer