【Unity】オブジェクトの現在速度を取得する

こじゃらこじゃら

オブジェクトが動いている速度を知りたい場合はどうすればいいの?

このはこのは

いくつか方法はあるけど、オブジェクトの移動量から知ることができるわ!

ゲームオブジェクトが現在動いている速度を知りたい場合、移動量移動した時間から計算することができます。

速度とは向きと大きさを持つ物理量です。本記事では、3次元空間での向きと大きさをベクトルとして得ることとします。

また、Rigidbodyで物理演算されているゲームオブジェクトは、上記計算をしなくても次のプロパティから簡単に知ることができます。

var rigidbody = GetComponent<Rigidbody>();
var velocity = rigidbody.velocity;

本記事では、ゲームオブジェクトが動いている現在速度を取得する方法を解説していきます。

この作品はユニティちゃんライセンス条項の元に提供されています

動作環境
  • Unity2021.1.23f1

スポンサーリンク

移動量から速度を計算するサンプル

最初に、3次元での移動速度を取得するサンプルスクリプトを示します。

CalcVelocityExample.cs
using UnityEngine;

public class CalcVelocityExample : MonoBehaviour
{
    // 1フレーム前の位置
    private Vector3 _prevPosition;

    private void Start()
    {
        // 初期位置を保持
        _prevPosition = transform.position;
    }

    private void Update()
    {
        // deltaTimeが0の場合は何もしない
        if (Mathf.Approximately(Time.deltaTime, 0))
            return;

        // 現在位置取得
        var position = transform.position;

        // 現在速度計算
        var velocity = (position - _prevPosition) / Time.deltaTime;

        // 現在速度をログ出力
        print($"velocity = {velocity}");

        // 前フレーム位置を更新
        _prevPosition = position;
    }
}

変数velocityに格納される値がオブジェクトの移動速度です。

実行結果

移動量から速度を計算する方法

前述のスクリプトで移動速度の計算ができる理由についても触れておきます。

速さと時間と距離の関係

まず、速さを求める計算について考えます。

速さとは、単位時間あたりに進む距離を表す物理量です。
速さ、移動にかかった時間、移動距離には、次式のような関係があります。

速さと時間と距離の関係式
s = \frac{x}{\Delta t}

s : 速さ
\Delta t : 移動にかかった時間
x : 移動距離

これは、移動にかかった時間\Delta tにおける平均の速さを求めることに等しいです。

速度と時間と変位の関係

速度とは、単位時間あたりにどの向きにどの距離だけ進むかを表す物理量です。

速さは大きさだけを表すのに対し、速度は大きさと向きを持っています。

時間\Delta tで位置がPからP’まで変化するとき、速度\vec{v}次式のように表せます。

速度と時間と変位の関係式
\vec{v} = \frac{P' - P}{\Delta t}

P’ – Pの部分は変位といい、移動した距離と向きを表します。

上式は、\Delta tにおける平均速度を求めることに等しいです。

現在速度を近似的に求める

平均速度を求める際、移動前と移動後の位置を求める時間\Delta t短くすると、現在速度により近い値が得られます。

この\Delta tを限りなく0に近づけたものが現在速度ですが、Unityには計測できる時間間隔に限度が存在します。 [1]

この最小限度の時間間隔はTime.deltaTimeプロパティから得られます。これは、UpdateFixedUpdateイベントの前フレームからの経過時間(秒)を表します。

UpdateとFixedUpdateイベントでは、イベントの発生タイミングが異なり、時間間隔も変わってきます。

しかし、Updateイベントでは前回のUpdateイベント発生からの経過時間、FixedUpdateイベントでは前回のFixedUpdateイベント発生からの経過時間という形で内部的に区別してくれるので、あまり気にする必要がありません。

Rigidbodyの移動速度を取得する

Rigidbodyにより物理演算されているオブジェクトの場合、Rigidbody.velocityプロパティから現在速度を取得できます。

注意点としては、物理演算されているオブジェクトの速度を取得できるものであり、transform.positionプロパティ等で直接位置を書き換えた場合は正しく速度を取得できません。

サンプルスクリプト

RigidbodyVelocityExample.cs
using UnityEngine;

public class RigidbodyVelocityExample : MonoBehaviour
{
    [SerializeField] private Rigidbody _rigidbody;

    private void FixedUpdate()
    {
        print($"velocity = {_rigidbody.velocity}");
    }
}

実行結果

さいごに

現在速度は、前フレームからの経過時間(Time.deltaTime)と変位(transform.positionの変化量)から計算できます。

Rigidbodyで物理演算されているオブジェクトの場合、Rigidbody.velocityから簡単に知ることができます。

オブジェクトの移動速度が分かれば、移動方向にキャラクターを回転させたり、弾を打つなど動作が可能になります。

是非活用を検討してみてください。

参考サイト

スポンサーリンク