22
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

グレンジAdvent Calendar 2018

Day 3

【Unity】Quaternionでゲームで使えそうな回転を作ってみた

Last updated at Posted at 2018-12-02

現在グレンジでUnityを用いたゲーム開発を行っているみくりやと申します。
グレンジ Advent Calendar 2018 3日目の記事になります。
去年も3日目だったな(ZenjectでDIの真理を悟る

QuaternionはUnityを使う人なら一度は通る道だと思います。Quaternionについての記事はたくさんありますが、今回はもうちょっと噛み砕いてゲームなどに応用しやすい初歩的な回転サンプルを作ってみたいと思います。

#Quaternionって?
細けぇことは一旦どうでもいいんだ、こいつは回転させてくれる

#注視する回転
指定オブジェクトを注視する回転です。

using UnityEngine;

public class QuaternionTest : MonoBehaviour {
    [SerializeField]
    private Transform _target;
    [SerializeField]
    private Transform _player;
	
	void Update () {
        LookTarget();
	}

    private void LookTarget() {
        _player.rotation = Quaternion.LookRotation(_target.position - _player.position);
    }
}

_player(Unityちゃん)が_target(とうふ)を見つめています。
transform.LookAtを使っているパターンもよく見かけますが、

Dec-01-2018 15-38-51.gif

#指定方向に回転
指定キーが押されている間、指定方向に回転する処理です。

public class QuaternionTest : MonoBehaviour {
    [SerializeField]
    private Transform _player;

	void Update () {
        if (Input.GetKey(KeyCode.LeftArrow)) {
            OnKeyPressRotate(1);
        } else if (Input.GetKey(KeyCode.RightArrow)) {
            OnKeyPressRotate(-1);
        }

	}

    private void OnKeyPressRotate(int direction) {
        _player.rotation *= Quaternion.AngleAxis(1f * direction, _player.up);
    }
}

Quaternion.AngleAxis指定軸に対する単位回転 を表すので、_playerの現在の回転にかけることで角度が加算されてくるくると回っていきます。
コードの例だとプレイヤーのy軸に対して1度回転します。

Dec-01-2018 16-07-10.gif

今度は指定キーを押したときに一定角度回転する動きを作ってみます。

public class QuaternionTest : MonoBehaviour {
    [SerializeField]
    private Transform _player;

    private Quaternion _startRotation;
    private Quaternion _endRotation;
    private float _countTime;
    private bool _startRotate;

	void Update () {
        if (Input.GetKeyDown(KeyCode.LeftArrow)) {
            OnKeyDownRotate(1);
        } else if (Input.GetKeyDown(KeyCode.RightArrow)) {
            OnKeyDownRotate(-1);
        }

        UpdateKeyDownRotate();
	}

    private void OnKeyDownRotate(int direction) {
        _countTime = 0f;
        _startRotation = _player.rotation;
        _endRotation = _player.rotation * Quaternion.AngleAxis(45f * direction, _player.up);
        _startRotate = true;
    }

    private void UpdateKeyDownRotate() {
        if (_startRotate == false) {
            return;
        }
        _countTime = Mathf.Clamp(_countTime + Time.deltaTime, 0f, 0.5f);
        float rate = _countTime / 0.5f;
        _player.rotation = Quaternion.Lerp(_startRotation, _endRotation, rate);

        if (rate >= 1f) {
            _startRotate = false;
        }
    }
}

Dec-01-2018 16-41-01.gif

指定キーを押したときに0.5秒かけて45度回転させています。
Quaternion.Lerpを用いて、_startRotationから_endRotationまで回転させていきます。
_endRotationの値は最初の例と同じ方法で指定しています。Quaternion自体は値なので動いているように見せるには今回のような方法が必要です。
rateの値を調節するとイージングをかけたりできますね。

#指定オブジェクト周りの回転
指定したオブジェクトの周りを回転させます

public class QuaternionTest : MonoBehaviour {
    [SerializeField]
    private Transform _target;
    [SerializeField]
    private Transform _player;
	
	void Update () {
        RotateArownd();
        LookTarget();
	}

    private void LookTarget() {
        _player.rotation = Quaternion.LookRotation(_target.position - _player.position);
    }

    private void RotateArownd() {
        _player.position = Quaternion.AngleAxis(1f, _target.up) * _player.position;
    }
}

Dec-01-2018 17-25-45.gif

プレイヤーの座標に回転をかけることでいい感じにオブジェクトの周りを回転してくれます。
しかし、このままだと_targetを動かしたときにおかしなことになります。

Dec-01-2018 17-28-53.gif

Quaternionは 原点を中心とした回転 を表すのでその点を考慮しなければなりません。(今回は_targetが原点にいたのでいい感じに見えてしまっていました)
RotateArownd()を以下のように改修します。

private void RotateArownd() {
    _player.position = _target.position + Quaternion.AngleAxis(1f, _target.up) * (_player.position - _target.position).normalized * 2f;
}

_targetから_playerに向いたベクトルをQuaternion.AngleAxisで回転させ_targetの座標に加算することで位置を算出します。こうすることで_target起点の回転を作ることができました。今回は半径2の位置に移動するようにnormalizedしたものに2をかけています。

Dec-01-2018 17-48-33.gif

「指定キーを押したときに一定角度回転する動き」で作ったものを応用することで「指定キーを押したときに指定オブジェクト周りを一定角度回転する」ということもできるでしょう。

#まとめ
今回作成したサンプルでは水平方向にしか回転させていませんが、Quaternionに指定する軸を変えることで回転方向を楽に変えることができるというのも便利なところです。
本記事であげた例以外にもQuaternionの使い方は様々あるので自身のプロジェクトにあった使い方を是非探してみてください。とっかかりに役立てれば幸いです。良きQuaternionライフを!

22
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?