UniRxを使って手軽にRPGのメニュー画面っぽいものを作ってみる

#はじめに
この記事はUnity #2 Advent Calendar 2017、12月14日の記事です。

今日は私の誕生日です。祝え

#出来上がるもの
![peti7_0317.gif](https://qiita-image-store.s3.amazonaws.com/0/61227/ea75d79d-8677-b212-f2db-dfa9ea629c0c.gif)


#準備
Unityで新規プロジェクトを作成し、AssetStoreからUniRxをインポートしてください。
無料なので気軽にー


#画面を用意する
こんな感じの画面を作ります。
右ビューは項目の数だけ作っておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61227/497535a3-cbc5-eb55-a2cd-dca97f5bb230.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61227/e9121746-c6b8-cb9b-e89c-ac177fe1f0a8.png)

#ボタンの設定をする
見出し以外の各テキストにはButtonコンポーネントを付け、
選択時の枠、ハイライト/押下時のみ枠が表示されるようにしておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61227/7fb94e5b-6d2e-dc63-7b6c-1da6f2cde5fe.png)

また、ボタンのナビゲーションをこんな感じに設定しておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61227/04b99ba6-51e4-f1d5-80fe-de152654d6e8.png)


#画面の表示タイプを示す列挙体を用意する
ここまで出来たらあとはスクリプトです。
まず、見出しの通りに列挙体を用意します。ついでにUniRx的に小細工をしておくといろいろ捗ります。



```csharp:ViewType.cs
using UniRx;

public enum ViewType{
	Menu,
	ViewA,
	ViewB,
	ViewC
}

[System.Serializable]
public class ViewTypeReactiveProperty : ReactiveProperty<ViewType>
{
	public ViewTypeReactiveProperty ()
	{
	}
}

#if UNITY_EDITOR
[UnityEditor.CustomPropertyDrawer(typeof(ViewTypeReactiveProperty))]
public class ViewTypeReactivePropertyDrawer : InspectorDisplayDrawer
{}
#endif
```

次に、状態管理＆メニュー表示用のスクリプトと、各画面制御用のスクリプトを用意します。
ボタンのバインドとかはUniRxでやってます。

```csharp:MenuViewScript.cs
using UnityEngine;
using UnityEngine.UI;
using UniRx;
using UnityEngine.EventSystems;

public class MenuViewScript : MonoBehaviour {
	public ViewTypeReactiveProperty m_viewType;

	[SerializeField]private Button m_btnA;
	[SerializeField]private Button m_btnB;
	[SerializeField]private Button m_btnC;

	void Start()
	{
		m_viewType.Subscribe (type => {
			if(type == ViewType.Menu)
			{
				EventSystem.current.SetSelectedGameObject(m_btnA.gameObject);
			}
		}).AddTo (this);

		m_btnA.OnClickAsObservable ().Subscribe (_ => {
			m_viewType.Value = ViewType.ViewA;
		}).AddTo (this);
		m_btnB.OnClickAsObservable ().Subscribe (_ => {
			m_viewType.Value = ViewType.ViewB;
		}).AddTo (this);
		m_btnC.OnClickAsObservable ().Subscribe (_ => {
			m_viewType.Value = ViewType.ViewC;
		}).AddTo (this);
	}
}


```
```csharp:SubViewScript.cs
using UnityEngine;
using UnityEngine.UI;
using UniRx;
using UnityEngine.EventSystems;

public class SubViewScript : MonoBehaviour {
	[SerializeField]private ViewType m_targetType;

	[SerializeField]private MenuViewScript m_mainScript;
	[SerializeField]private Button m_backBtn;
	void Start () {
		m_mainScript.m_viewType.Subscribe (type => {
			if(type == m_targetType)
			{
				this.gameObject.SetActive (true);
				EventSystem.current.SetSelectedGameObject(m_backBtn.gameObject);
			}else{
				this.gameObject.SetActive (false);
			}
		}).AddTo (this);

		m_backBtn.OnClickAsObservable ().Subscribe (_ => {
			m_mainScript.m_viewType.Value = ViewType.Menu;
		}).AddTo (this);
	}
}

```

#Inspectorで設定する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61227/ab48681f-dfcf-7392-16fc-622b4c83f2db.png)
ちなみに先ほどの小細工のおかげで、ここのViewTypeをいじることでメニューを変更できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61227/70bf3baa-ef97-574f-9381-5f9447c0d79f.png)
(ViewB/ViewCはほぼ同じため割愛)

#ゲームを実行する
どーん！
![peti7_0317.gif](https://qiita-image-store.s3.amazonaws.com/0/61227/ea75d79d-8677-b212-f2db-dfa9ea629c0c.gif)


#この書き方の利点
ViewTypeに項目を追加するだけで、簡単に画面数を増やすことができます。
また、各機能がほぼ独立しているため、変更が容易です。

#あとがき
ちょっと時間がないので書き逃げ気味ですが、ReactivePropertyだけでもいろいろと使えますし、
かなりシンプルにいろいろなことができます。
(ちなみにこのサンプルプロジェクト作るのに10分くらい)
試しに触ってみるといいかもです。

明日はsakuo_sundayさんの「unityとarduinoで何かします。」です。