はじめに
Unityでキャラクターの方向転換をしたいときに、なめらかに方向転換する方法をまとめました。
Playerを準備する
Hierarchyウィンドウで右クリック→Create Emptyで空のゲームオブジェクトを作成し、名前をPlayerとします。
さらに、Hierarchyウィンドウで右クリック→3D Objectから、CubeとSphereを生成します。
これらをHierarchyウィンドウの中で、Playerにドッグ&ドロップして子要素にします。
最後に、Sphereの位置を少しずらして下画像のようにします。これでPlayerがどちらを向いているか分かるようになりました。
Scriptを書く
ProjectウィンドウのAssets内で右クリック→Create→C# Scriptの順に操作します。
生成されたファイル名をPlayerとしておきます。
出来上がったファイルをHierarchyウィンドウのPlayerにAdd Componentします。
それでは中身を書いていきます。Playerファイルをダブルクリックで開きます。
以下のようにコードを記述します。
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型の比較方法です。
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を超えてしまうのでそれを補正するためです。今回は移動は実装しないのであまり関係ありませんが、実装する際はやった方がいいと思います。
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で設定します。
使い方は後述します。
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);でキャラクターを回転させます。
第1引数から第2引数へ、最大でも第3引数の角度分だけ回転させたQuaternionを返します。
これにより、1フレーム内でも最大でもRotateSpeed * Time.deltaTimeしか回転しないため、キャラクターがなめらかに回転します。
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を小さくすればもっとゆっくりと回転するようになります。
まとめ
今回はキャラクターをなめらかに回転させる方法についてまとめました。
汎用性がある内容だと思いますのでぜひ試してみてください。