【Unity】キャラクターをなめらかに方向転換させる

# はじめに
Unityでキャラクターの方向転換をしたいときに、なめらかに方向転換する方法をまとめました。

# Playerを準備する
Hierarchyウィンドウで右クリック→Create Emptyで空のゲームオブジェクトを作成し、名前をPlayerとします。
さらに、Hierarchyウィンドウで右クリック→3D Objectから、CubeとSphereを生成します。
これらをHierarchyウィンドウの中で、Playerにドッグ&ドロップして子要素にします。
最後に、Sphereの位置を少しずらして下画像のようにします。これでPlayerがどちらを向いているか分かるようになりました。
![スクリーンショット 2022-07-17 11.12.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729622/97f49103-b33d-e7f1-e56b-63aba9440133.png)

# Scriptを書く
ProjectウィンドウのAssets内で右クリック→Create→C# Scriptの順に操作します。
生成されたファイル名をPlayerとしておきます。
出来上がったファイルをHierarchyウィンドウのPlayerにAdd Componentします。

それでは中身を書いていきます。Playerファイルをダブルクリックで開きます。
以下のようにコードを記述します。
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    private const float RotateSpeed = 720f;

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

    // Update is called once per frame
    void Update()
    {
        Vector3 direction = InputToDirection();
        float magnitude = direction.magnitude;

        if (Mathf.Approximately(magnitude, 0f) == false)
        {
            UpdateRotation(direction);
        }
    }

    private Vector3 InputToDirection() {
        Vector3 direction = new Vector3(0f, 0f, 0f);

        if (Input.GetKey(KeyCode.RightArrow))
        {
            direction.x += 1f;
        }

        if (Input.GetKey(KeyCode.LeftArrow))
        {
            direction.x -= 1f;
        }

        if (Input.GetKey(KeyCode.UpArrow))
        {
            direction.z += 1f;
        }

        if (Input.GetKey(KeyCode.DownArrow))
        {
            direction.z -= 1f;
        }

        return direction.normalized;
    }

    private void UpdateRotation(Vector3 direction)
    {
        Quaternion from = transform.rotation;
        Quaternion to = Quaternion.LookRotation(direction);
        transform.rotation = Quaternion.RotateTowards(from, to, RotateSpeed * Time.deltaTime);
    }
}
```
Updateメソッドの中身を解説します。
まず、InputToDirection()で入力された方向を取得します。
次に、direction.magnitudeでベクトルの大きさを取得します。
そして、magnitudeと0を比較して、近似していない場合（ベクトルが0でない場合）にUpdateRotationメソッドで向きを変えます。Mathf.Approximatelyは不動小数点の誤差を考慮したfloat型の比較方法です。
```cs
    void Update()
    {
        Vector3 direction = InputToDirection();
        float magnitude = direction.magnitude;
        if (Mathf.Approximately(magnitude, 0f) == false)
        {
            UpdateRotation(direction);
        }
    }
```
InputToDirectionメソッドを定義します。
まず、directionを0ベクトルとして初期化します。
あとは、入力されたキーの方向で条件分岐をしてdirectionのxまたはzを更新するだけです。
returnでは長さ1のベクトルにしてdirectionを返しています。これは斜め方向へ移動する際に長さが1を超えてしまうのでそれを補正するためです。今回は移動は実装しないのであまり関係ありませんが、実装する際はやった方がいいと思います。

```cs
    private Vector3 InputToDirection() {
        Vector3 direction = new Vector3(0f, 0f, 0f);

        if (Input.GetKey(KeyCode.RightArrow))
        {
            direction.x += 1f;
        }

        if (Input.GetKey(KeyCode.LeftArrow))
        {
            direction.x -= 1f;
        }

        if (Input.GetKey(KeyCode.UpArrow))
        {
            direction.z += 1f;
        }

        if (Input.GetKey(KeyCode.DownArrow))
        {
            direction.z -= 1f;
        }

        return direction.normalized;
    }
```
最後にUpdateRotationを解説します。ここが今回のメインです。
まず初めに、キャラクターを回転させる角度をRotateSpeedで設定します。
使い方は後述します。

```cs
public class Player : MonoBehaviour
{
    private const float RotateSpeed = 720f;

    // Start is called before the first frame update
    void Start()
    {
        
    }
```
UpdateRotationの中身を解説します。
directionを引数に取り、その方向へキャラクターを回転させるメソッドです。

まず、Quaternion from = transform.rotation;で回転前のキャラクターの向きを取得します。Quaternionは回転を扱うための型です。

次に、Quaternion to = Quaternion.LookRotation(direction);でキャラクターが回転する方向を取得します。Quaternion.LookRotationは与えられた方向のベクトルを向くQuaternionを返すメソッドです。

最後の、transform.rotation = Quaternion.RotateTowards(from, to, RotateSpeed * Time.deltaTime);でキャラクターを回転させます。
第１引数から第２引数へ、最大でも第３引数の角度分だけ回転させたQuaternionを返します。
これにより、１フレーム内でも最大でもRotateSpeed * Time.deltaTimeしか回転しないため、キャラクターがなめらかに回転します。
```cs
    private void UpdateRotation(Vector3 direction)
    {
        Quaternion from = transform.rotation;
        Quaternion to = Quaternion.LookRotation(direction);
        transform.rotation = Quaternion.RotateTowards(from, to, RotateSpeed * Time.deltaTime);
    }
```

# 動作確認
gifなので少し分かりづらいかもですが、なめらかに方向転換できています。
RotateSpeedを小さくすればもっとゆっくりと回転するようになります。
![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729622/62f0d0fb-58c8-77e7-808b-c28d0fb4868c.gif)

# まとめ
今回はキャラクターをなめらかに回転させる方法についてまとめました。
汎用性がある内容だと思いますのでぜひ試してみてください。