シータ＋Oculusでスライドショーしてみた。（ステートチャート編）（コード付き）

動作
===
![Clipboard02.jpg](https://qiita-image-store.s3.amazonaws.com/0/32364/40a65213-4c8b-be94-8c15-72fedad3bb2a.jpeg)
上記みたいな感じのRicoh Thetaで撮影された写真を背景を設定された時間毎に切り替えます。
要はスライドショーです。
実はアセットを使用して色々エフェクトを作っているバージョンも有るのですが
今回はコードも含めて公開するため削除しました。

サンプルコード
Your own risk.で適当に使ってください。
http://bowlroll.net/up/dl28986
紹介ムービー（ニコニコ動画）
http://www.nicovideo.jp/watch/sm22430710


ステートチャート
===
![131201 UML_0.jpg](https://qiita-image-store.s3.amazonaws.com/0/32364/6238a951-5eee-94f7-fd46-93602c615350.jpeg)

実装的にはステートチャートを中心として動いています。
なので今回の記事ではステートチャートのデザインとそれをコードに落としこむための
我流の方法を紹介したいと思います。

「P_SYOMEN_IN～P_SYOMEN_OUT」までが再生前の調整用の状態になります。
---
１，P_SYOMEN_IN
> フェードインします。

２，P_SYOMEN
> 「正面」と書かれた文字が正面に出てきます。
> ジョイスティックのボタンを押して正面の位置をリセットします。
> ジョイスティックのボタンで再生が開始（矢印の方向へ遷移）されます。

３，P_SYOMEN_OUT
> フェードアウトします。

「P_FADE_IN～P_FADE_OUT」までが再生中の状態になります。
---
４，P_FADE_IN
> m_EnterPlsを見て現在の画像をシェーダーへ設定します。
> フェードインします。

５，P_PLAY
> 指定時間分画像を表示します。
> 途中でボタン入力が有った場合は強制終了としてP_END_FADE_OUTへ遷移します。

６，P_FADE_OUT
> フェードアウトします。
> 次の画像へ進めてP_FADE_INへ遷移します。

終了時の処理
---
７，P_END_FADE_OUT
> フェードアウトします。
> タイマーによる終了後はP_SYOMEN_INへ遷移します。

実装
===
ちなみに、ちまたではGofのStateパターンというのが流行ってるらしいですが僕は我流で作っています。
あのやり方だといっぱいクラス作らなきゃいけないので手間がかかります。
なので、僕の場合は一つの関数に一つの状態を割り振ります。
以下のコードは煩雑な部分を省いた骨組みだけのコードになります。

```csharp:ステートチャート

public class state : MonoBehaviour {

	//各ステートをenumで定義
	public enum STATE
	{
		P_BLANK,
		P_SYOMEN_IN,
		P_SYOMEN,
		P_SYOMEN_OUT,

		P_FADE_IN,
		P_PLAY,
		P_FADE_OUT,
		P_END_FADE_OUT
	}

	bool m_EnterPls;//状態遷移時の一回目の時だけtrueになります。
	public STATE m_State = STATE.P_SYOMEN_IN;//現在の状態を保持します。
	STATE m_StateOld = STATE.P_BLANK;//一個前に実行した状態を保持します。

	//ステートチャートの実装
	void StateChart()
	{
		//ステート変更後、enterを作りやすいために書いておきます。
		if (m_State != m_StateOld)
		{
			m_StateOld = m_State;
			m_EnterPls = true;
		}
		else
		{
			m_EnterPls = false;
		}

		//各ステート毎の関数へ割り振り
		switch (m_State )
		{
			case (STATE.P_SYOMEN_IN ):
				SSyomenIn();
				break;

			case (STATE.P_SYOMEN):
				SSsyomenPlay();
				break;

			case (STATE.P_SYOMEN_OUT):
				SSyomenOut();
				break;

			case (STATE.P_FADE_IN ):
				SFadeIn();
				break;

			case (STATE.P_PLAY ):
				SPlay();
				break;

			case (STATE.P_FADE_OUT ):
				SFadeOut();
				break;

			case (STATE.P_END_FADE_OUT):
				SEndFadeOut();
				break;
		}
	}

	//各種ステートの処理
	void SSyomenIn(){ }
	void SSsyomenPlay() { }
	void SSyomenOut(){ }
	void SFadeIn() { }
	void SPlay() { }
	void SFadeOut(){ }
	void SEndFadeOut() { }
}

```

ポイント
===
ステートチャートで重要な機能はいくつか有ります。
１，状態(ステート)を維持し、それを遷移させること
２，状態を遷移させた際に関数を実行させる。
３，状態が持つことが出来る下記三点の関数を実行する。
・Enter（状態に入った時）
・Do(状態に入っている最中ずっと)
・Exit(状態を出る時)
これらを全て実現可能であることが求められます。
上のコードでは全て実現可能になっています。

１，状態(ステート)を維持し、それを遷移させること
---

状態の維持、遷移については「m_State」で全て行っています。
「m_State」へ数値を代入することで遷移を行います。

２，状態を遷移させた際に関数を実行させる。
---
遷移させる際の処理は正直な所ちゃんと完備していません。
代用の手段として「m_State」へ数値を代入するタイミングで同時に処理を実行します。
下記の例では遷移するついでに数値に0.0fを代入しています。

```csharp:例

		if (m_SyomenTime > 1.0f)
		{
			m_State = STATE.P_SYOMEN;
			fadeAspect = 0.0f;
		}

```

３，状態が持つことが出来る下記三点の関数を実行する。
---
単体の状態の実装を見てどのように実装しているかを確認します。
下記の３つをどう実装されているかコメントを入れました。
・Enter（状態に入った時）
・Do(状態に入っている最中ずっと)
・Exit(状態を出る時)


```csharp:例

	//各種ステートの処理
	void SSyomenIn()
	{
		//Enter（状態に入った時）
		if (m_EnterPls)
		{
			m_PictNowNum = 0;
			m_PictRend.material.SetTexture("_MainTex", m_ShomenTexture);
			m_PictSphere.transform.rotation = Quaternion.identity ;
			m_PictSphere.transform.localScale = new Vector3(50.0f,50.0f,50.0f);

			m_EffectManager.SetEffect( -1 );
			m_SyomenObj.SetActive(true);
			m_SyomenTime = 0.0f;
			
		}

		//Do(状態に入っている最中ずっと)
		m_SyomenTime += Time.deltaTime;

		
		float fadeAspect;
		if (m_SyomenTime > 1.0f)
		{
			//Exit(状態を出る時)
			m_State = STATE.P_SYOMEN;
			fadeAspect = 0.0f;
		}
		else
		{
			//Do(状態に入っている最中ずっと)
			fadeAspect = 1.0f - (m_SyomenTime / 1.0f);
		}
		//Do(状態に入っている最中ずっと)
		m_BlackRend.materials[0].SetColor("_TintColor", new Color(0.5f, 0.5f, 0.5f, fadeAspect * 0.5f));
	}
```

終わりに
===
以上によりステートチャートの少し変わった実装方法の説明は終わりになります。
実際の使用方法はサンプルコードを確認してみるor自分でも試してみてください。

写真については@Tomohangさん撮影になります。
音楽についてはうえさんよりお借りしています。