二回目のStateMachine　オブジェクトの切り替え

状態によってオブジェクトを切り替える．

# 今回作るもの
- 青いCubeの時は横移動できる．
- 赤いCubeの時はうごけない．

![result3.gif](https://qiita-image-store.s3.amazonaws.com/0/113504/cb8d6753-0020-5b85-18b2-e2666a2e5ad7.gif "result3.gif")



# Playerの親子構造
- Player // 本体．　スクリプトをつけるやつ
	- Player1 //赤いCube
	- Player2 //青いCube


# 前提

StateMachineの理論が分かり,if文を使って実装できること．
[多分これが一番簡単なStateMachineだと思います．](http://qiita.com/Teach/items/36ee92916eaca60dcac5)

# 1. 状態を変えられるようにする．

まずは，前回と同じように，状態を切り替える部分をつくります．
## 手順
1. 状態をintで宣言．
2. if文で各状態での行うことを分ける．
3. 状態変更を書く．

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

public class PlayerScript : MonoBehaviour {

	int currentState = 0; // 0: Blue    1: Red

	void Update () {

		// state: Blue
		if (currentState == 0) {
			Debug.Log ("Blue");

			// 状態変更
			if (Input.GetKeyDown (KeyCode.R)) {
				currentState = 1;
			}
		}

		// state: Red
		if (currentState == 1) {
			Debug.Log ("Red");

			if(Input.GetKeyDown(KeyCode.B)){
				currentState = 0;
			}
		}
	}
}

```

# 2. プレイヤー作る
今回は非常に簡単です．

## 手順
1. Cubeを二つ作る．
2. それぞれにマテリアルをつけ，青と赤にする．名前はPlayer1, Player2とでもしましょう．
3. 親子関係を図のようにする．


![スクリーンショット 2016-06-12 12.39.58.png](https://qiita-image-store.s3.amazonaws.com/0/113504/e2390b23-5c12-a4ea-9a9b-772894a4d624.png "スクリーンショット 2016-06-12 12.39.58.png")

4. Player2のみ非アクティブにする．
![nonactive.jpg](https://qiita-image-store.s3.amazonaws.com/0/113504/eb77b11c-9eb9-9a68-b935-c72ebe055bc4.jpeg "nonactive.jpg")
5. Player1とPlayer2の場所を(0,0,0)にする


# 3. オブジェクトの切り替え
## 手順
1. 切り替える対象を変数に格納
2. 現在のオブジェクトを宣言
3. 切り替える関数を作る．
4. 状態が変わるときに関数を呼び出す．

## 3.1 切り替える対象を変数に格納

```csharp
public GameObject blueObject;
public GameObject redObject;
```

## 3.2 現在のオブジェクトを宣言

プレイヤーの今でてる状態(オブジェクト)を表す，currentObjectを宣言します．

```csharp
private GameObject currentObject;
```

## 3.3 切り替える関数を作る．

### 手順

引数に切り変える対象オブジェクトを入れ，
1. 現在のオブジェクトを非アクティブにする．
2. 次のオブジェクトを`currentObject`に代入
3. アクティブにする．


スクリプトは以下のようになります．

```csharp
void ChangeMode(GameObject obj){
	currentObject.SetActive(false);
	currentObject = obj;
	currentObject.SetActive (true);
}
```

# 3. 移動機能
以下のスクリプトを`currentState`が0のときに行います．

```csharp
// 移動
if (Input.GetKey (KeyCode.RightArrow)) {
	this.transform.position += Vector3.right * Time.deltaTime * 5f;
}
	
if (Input.GetKey (KeyCode.LeftArrow)) {
	this.transform.position += Vector3.right * (-1) * Time.deltaTime * 5f;
}
```

## 完成
1. Playerにスクリプトアタッチ
2. inspectorビューでPlayer1とPlayer2でアタッチ
3. 実行

```PlayerScript.cs
using UnityEngine;
using System.Collections;

public class PlayerScript : MonoBehaviour {

	public GameObject blueObject;
	public GameObject redObject;

	private GameObject currentObject;

	int currentState = 0; // 0: Blue    1: Red

	void Start () {
		currentObject = blueObject;
	}

	void Update () {

		// state: Blue
		if (currentState == 0) {
			Debug.Log ("Blue");

			// 移動
			if (Input.GetKey (KeyCode.RightArrow)) {
				this.transform.position += Vector3.right * Time.deltaTime * 5f;
			}
				
			if (Input.GetKey (KeyCode.LeftArrow)) {
				this.transform.position += Vector3.right * (-1) * Time.deltaTime * 5f;
			}

			// 状態変更
			if (Input.GetKeyDown (KeyCode.R)) {
				currentState = 1;
				ChangeMode (redObject);
			}
		}

		// state: Red
		if (currentState == 1) {
			Debug.Log ("Red");

			if(Input.GetKeyDown(KeyCode.B)){
				currentState = 0;
				ChangeMode (blueObject);
			}
		}
	}

	void ChangeMode(GameObject obj){
		currentObject.SetActive(false);
		currentObject = obj;
		currentObject.SetActive (true);
	}
}

```

# 練習問題
## 問題1
青 -> 赤 -> 緑　で変化するようにせよ.

## 問題2
緑のときだけ，Y軸で回転するようにせよ．


###### ヒント
```csharp
this.tranform.Rotate(Vector3.up * rotateSpeed * Time.deltaTime, Space.World);
```

## 問題3
問題2でできたスクリプトを，下の「最後に」のように，きれいなコードでかけ．

# 最後に　コードをきれいにする．
if文を使った実装では，
1. 状態遷移を切り替えるためのキーを同じキーにできない．
2. ぱっと見わかりにくい
という欠点があります．


そこで，switch文を使うことでそれらの問題を解決することができます．

また，他をいろいろきれいにします．(雑

後で別の記事つくります．

```PlayerScript.cs
using UnityEngine;
using System.Collections;

public class PlayerScript : MonoBehaviour {
	
	//切り替わるオブジェクト
	public GameObject blueObject;
	public GameObject redObject;
	
	//現在のオブジェクト
	private GameObject currentObject;

	//状態を定義
	public enum PlayerState
	{
		BLUE,
		RED
	}

	//現在の状態
	private PlayerState _currentState;

	void Start () {
		InitState ();
	}

	void Update () {
		switch (_currentState) {
		case PlayerState.BLUE:
			UpdateBlue ();
			break;
		case PlayerState.RED:
			UpdateRed ();
			break;
		default:
			break;
		}
		Debug.Log (_currentState);
	}

	//状態の初期化
	void InitState(){
		_currentState = PlayerState.BLUE;
		currentObject = blueObject;
	}
	
	//状態がBlueのときにやること
	void UpdateBlue(){
		if (Input.GetKey (KeyCode.RightArrow)) {
			this.transform.position += Vector3.right * Time.deltaTime * 5f;
		}

		if (Input.GetKey (KeyCode.LeftArrow)) {
			this.transform.position += Vector3.right * (-1) * Time.deltaTime * 5f;
		}

		if (Input.GetKeyDown (KeyCode.C)) {
			_currentState = PlayerState.RED;
			ChangeMode (redObject);
		}
	}
	
	//状態がRedのときにやること
	void UpdateRed(){
		if (Input.GetKeyDown (KeyCode.C)) {
			_currentState = PlayerState.BLUE;
			ChangeMode (blueObject);
		}
	}

	//オブジェクトの切り替え
	void ChangeMode(GameObject obj){
		currentObject.SetActive(false);
		currentObject = obj;
		currentObject.SetActive (true);
	}
}
```