Unityで回転させたかっただけなのに結構大変だったお話

**(´・ω・)「矢印キーで回転する3Dオブジェクトを作りたいんだけどどうすれば良い？」**


と聞かれたので、実際にサンプルを作ってみることにした。

##矢印キーで回転する3Dオブジェクトを作る
###オブジェクトをつくろう！
まずはヒエラルキータブの上で右クリック→「3D Object」→「Cube」で箱を作る。
![blog1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/a182311e-3f6c-750b-eefe-31e7031196f0.png)

回転しているのがわかりやすいようにインスペクタタブでScaleを適当に調整する。
![blog2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/eadfbf4d-ccf9-dd71-02de-c37eef67c4bc.png)


以下のようなオブジェクトができるはず。
![blog3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/f389f0bc-8d31-3b43-0422-dc38f970ceed.png)

###スクリプトをつくろう！
Assetsの中にScriptというフォルダを作って、「Create」→「C# Script」でスクリプトファイルを作成する。
![blog5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/ffba2e55-2a20-ead6-20bf-0f0107e7f5d8.png)


矢印キーを押下したら90度ずつ回転するようにするようにUpdateメソッド内に実装する。

```C#:CubeKaiten.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeKaiten : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        // ↑キー押下時
		if (Input.GetKeyDown(KeyCode.UpArrow)) {
			transform.Rotate(new Vector3(0f, 0f, 90f));
        }
        // ↓キー押下時
		if (Input.GetKeyDown(KeyCode.DownArrow)) {
			transform.Rotate(new Vector3(0f, 0f, -90f));
        }
        // →キー押下時
		if (Input.GetKeyDown(KeyCode.RightArrow)) {
			transform.Rotate(new Vector3(90f, 0f, 0f));
        }
        // ←キー押下時
		if (Input.GetKeyDown(KeyCode.LeftArrow)) {
			transform.Rotate(new Vector3(-90f, 0f, 0f));
        }
    }
}

```
##アタッチして動かそう！

先ほど作ったスクリプトを作ったオブジェクトにアタッチして動かしてみる。
![image1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/156d2615-eeef-3887-47bb-00f007a564d6.gif)


これでどうだ！


**(´・ω・)「カクカク回転じゃなくて滑らかに回転して欲しいなぁ」**


と言われたのでもう一度考え直す・・・・。

## 3Dオブジェクトを滑らかに回転させる

### スクリプトを修正する
先ほどのスクリプトでは一気に90度回ってしまうため2度ずつ45回にかけて回るようにスクリプトを修正する。

```C#:CubeKaiten.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeKaiten : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        // ↑キー押下時
		if (Input.GetKeyDown(KeyCode.UpArrow)) {
			Animation(new Vector3(0f, 0f, 2f));
        }
        // ↓キー押下時
		if (Input.GetKeyDown(KeyCode.DownArrow)) {
			Animation(new Vector3(0f, 0f, -2f));
        }
        // →キー押下時
		if (Input.GetKeyDown(KeyCode.RightArrow)) {
			Animation(new Vector3(2f, 0f, 0f));
        }
        // ←キー押下時
		if (Input.GetKeyDown(KeyCode.LeftArrow)) {
			Animation(new Vector3(-2f, 0f, 0f));
        }
    }
    
    // 2度ずつ回転を45回行う
    private void Animation(Vector3 angle) {
    	for(int i=0; i<45; i++){
    		transform.Rotate(angle);
    	}
    }
    
}
```

保存し再度動かしてみる。

![image2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/1bfa72fd-49fe-6b48-d490-2ce922bb7ec7.gif)

**(´・ω・)「さっきと変わってないやん！！」**

### なんでこれだとダメなのか？

Update()メソッドは毎フレームごとに呼ばれる。
つまり45回for文で回したとしても、一瞬で終わってしまう。
というわけで、再度考え直し・・・。

```C#:CubeKaiten.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeKaiten : MonoBehaviour
{

	// アニメーション中かどうか
    bool isAnimate;
    // 回転の角度
    Vector3 angle;
    // 回転回数
    int count;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
    	// アニメーションを行うかの判定
    	if (isAnimate) {
			Animation();
		}
    
        // ↑キー押下時
		if (Input.GetKeyDown(KeyCode.UpArrow)) {
			isAnimate = true;
			angle = new Vector3(0f, 0f, 2f);
			count = 0;
        }
        // ↓キー押下時
		if (Input.GetKeyDown(KeyCode.DownArrow)) {
			isAnimate = true;
			angle = new Vector3(0f, 0f, -2f);
			count = 0;
        }
        // →キー押下時
		if (Input.GetKeyDown(KeyCode.RightArrow)) {
			isAnimate = true;
			angle = new Vector3(2f, 0f, 0f);
			count = 0;
        }
        // ←キー押下時
		if (Input.GetKeyDown(KeyCode.LeftArrow)) {
			isAnimate = true;
			angle = new Vector3(-2f, 0f, 0f);
			count = 0;
        }
    }
    
    // 2度ずつ回転を45回行う
    private void Animation() {
    	
    	transform.Rotate(angle);
    	count++;
    	
		// 45回回ったら終了
		if(count == 45) {
    		isAnimate = false;
    	}
    }    
}

```
矢印キー押下でAnimationを呼び出し、45回回ったらAnimationを終了させるという風に書いてみた。

これでどうだ！

![image3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/7843160a-28e0-3295-1e82-49326d75256e.gif)


**(´・ω・)「滑らかになったー！けど回る方向が途中でおかしくなるぞ！」**
(↑だと分かりにくいですが、実際に動かすと時々逆回転します)

###ワールド座標とローカル座標

色々調べていると、ワールド座標とローカル座標というのにたどり着いた。
ワールド座標は原点から見た座標になり、ローカル座標は親オブジェクトからの座標になる。

ということは、回すときにワールド座標を基準とすればうまくいくのではないかと思い、修正。

```C#:CubeKaiten.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeKaiten : MonoBehaviour
{

	// アニメーション中かどうか
    bool isAnimate;
    // 回転の角度
    Vector3 angle;
    // 回転回数
    int count;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
    	// アニメーションを行うかの判定
    	if (isAnimate) {
			Animation();
		}
    
        // ↑キー押下時
		if (Input.GetKeyDown(KeyCode.UpArrow)) {
			isAnimate = true;
			angle = new Vector3(0f, 0f, 2f);
			count = 0;
        }
        // ↓キー押下時
		if (Input.GetKeyDown(KeyCode.DownArrow)) {
			isAnimate = true;
			angle = new Vector3(0f, 0f, -2f);
			count = 0;
        }
        // →キー押下時
		if (Input.GetKeyDown(KeyCode.RightArrow)) {
			isAnimate = true;
			angle = new Vector3(2f, 0f, 0f);
			count = 0;
        }
        // ←キー押下時
		if (Input.GetKeyDown(KeyCode.LeftArrow)) {
			isAnimate = true;
			angle = new Vector3(-2f, 0f, 0f);
			count = 0;
        }
    }
    
    // 2度ずつ回転を45回行う
    private void Animation() {
    	
    	transform.Rotate(angle,Space.World);
    	count++;
    	
		// 45回回ったら終了
		if(count == 45) {
    		isAnimate = false;
    	}
    }    
}

```

Animation()内のtransform.Rotateにangle,Space.Worldを引数で渡すように修正。

![image4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318640/4433102b-b8d8-31a8-2d06-e6861dda3235.gif)

やったー！ちゃんと回したい方向に回るぞー！

でもこの3Dオブジェクトって親がいない気が・・・？ここが未だに解決できてないけど一旦やりたいことは出来た。回転させるのって結構大変・・。