【Unity】Lerpとは?線形補間して滑らかな移動や回転を行うメソッド

線形補間を行うLerpとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「UnityのLerpってなに?」

「Lerpメソッドってどういう処理を行うの?」

というお悩みの方に向けた内容となっています。

Lerpとは、Linear Interpolateの英語の略で、線形補間と呼ばれる処理を行ってくれるメソッドです。

この線形補間というのは、2つの値の間の数値を、直線を使って近似的に補うことを言います。

例えば、オブジェクトの移動処理を作る際に、Lerpメソッドで返された値を使うことで、特定の地点まで直線に進み、かつ滑らかな移動を行うことができます。

そこで、このページでは、Unityで使えるLerpメソッドについて、どんなメソッドなのか、また使い方までをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

Lerpとは?線形補間を使って滑らかな処理を作れるメソッド

まずは、Lerpメソッドがどういうメソッドなのかを紹介していきます。

冒頭でも解説した通り、Lerpメソッド線形補間を行うメソッドで、Vector3・Mathf・Quaternionの構造体で定義されていて、主にオブジェクトの移動などを滑らかにする処理を行います。

この線形補間というのは、直線を使って2つの間の値を近似的に求めて補うことを指しています。

補間と聞くとなんだか難しそうですが、簡単に言えば2つの間を埋める作業を行っています。

例えば、それぞれ異なる場所に2つの点AとBがあり、このA地点からB地点にオブジェクトを移動させるとします。

ある程度Unityを触っていると分かりますが、A地点にあるオブジェクトの座標(position)に、B地点の座標を入れたら、当然オブジェクトは移動というよりもワープするだけになります。

このオブジェクトを移動させる処理を作る際に、AとBを繋いだ直線があると想定して、この直線の間の座標を求めて埋めてあげることで、その座標を代入してオブジェクトを移動させることができるようになります。

このように2つの点を直線で繋いで、その間の数値や地点などを埋めてあげることを線形補間と呼びます。

ここでは、分かりやすい座標(Vector3)を例にあげましたが、Lerpメソッドには、数値(Mathf)回転(Quaternion)における線形補間も、同じような仕組みで処理されます。

なお、同じように補間してくれるメソッドに、Slerpメソッドというものがありますが、このSlerpメソッドは、直線ではなく球面を想定して補間する「球面線形補間」という処理を行います。

Lerpの使い方

ここからは、実際にLerpメソッドの使い方を紹介していきます。

引数で2つの値と補間する位置を設定する

Lerpメソッドを使う際は、引数に2つの値補間する位置を設定して使います。

例えば、Vector3のLerpメソッドであれば、以下のようになります。

Vector3.Lerp(a, b, t);

a:始点となるVector3型の値
b:終点となるVector3型の値
t:直線上で補間する位置(0から1までのfloat型)

tの補間する位置は、aを0、bを1とした際の直線上での割合(位置)のことを指しています。

つまり、その直線におけるtで指定した位置のVector3型の値が、Lerpメソッドによって返されることになります。

また、Vector3以外の型で使う場合は、Mathf.Lerpであれば引数にfloat型の値を設定、Quaternion.Lerpであれば引数にQuaternionの値を設定することで、tで指定した位置のそれぞれの型の値が返ってくることになります。

Lerpを使った実例

ここからは、UnityでLerpメソッドを使って、オブジェクトなどを実際に動かしてみます。

オブジェクトを滑らかに移動させる処理

キューブのオブジェクトを現在の位置から、空オブジェクトで指定した場所に移動させるという処理を作ってみます。

キューブのオブジェクトに以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    public GameObject target;   // 空オブジェクトを取得
    Vector3 startPosition;  // スタート地点を取得

    void Start()
    {
        startPosition = transform.position; // 最初にオブジェクトがいた場所を取得
    }

    void Update()
    {
        transform.position = Vector3.Lerp(startPosition, target.transform.position, Time.time / 2); // 線形補間した値を代入して移動させる処理
    }
}

15行目でVector3.Lerpメソッドを使って、補間したベクトル値をオブジェクトの座標に代入しています。

始点となる座標をオブジェクトが最初にいた地点、終点となる座標を空オブジェクトの地点に設定しています。

また補間位置には、「Time.time」ゲーム実行時からの時間を計測する変数を使っていて、2で割った値を設定しています。

つまり、ゲームスタートから2秒経過すると補間値が1となり、終点の座標が代入されることになるので、2秒で目的地に到着するという処理が行われます。

実際にゲームを動かしてみると、

キューブのオブジェクトが空オブジェクトで指定した場所までまっすぐに進み、2秒で到着するという処理が作れました。

カメラを少し遅らせて移動させる処理

次は、オブジェクトに追従するカメラオブジェクトを、少し遅らせて移動する処理を作ってみます。

まず、適当なオブジェクトを配置して、キー操作で横移動させる処理をスクリプトに記述しておきます。

using UnityEngine;

public class CapsuleController : MonoBehaviour
{
    void Update()
    {
        transform.position += new Vector3(Input.GetAxis("Horizontal") * 0.01f, 0f, 0f); // オブジェクトをキー操作で横移動させる処理
    }
}

次に、カメラオブジェクトに以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test2 : MonoBehaviour
{
    public GameObject capsule;  // オブジェクトを取得する

    void Update()
    {
        transform.position = new Vector3(capsule.transform.position.x, transform.position.y, transform.position.z); // X軸をオブジェクトのX軸の値を指定する
    }
}

これで一旦ゲームをスタートしてみると、

オブジェクトを動かすと、カメラも追従して動いているのが分かります。

次に、このカメラのスクリプトに、Lerpメソッドで処理を加えてみます。

using UnityEngine;

public class Test2 : MonoBehaviour
{
    public GameObject capsule;  // オブジェクトを取得する
    float targetPosX;   // 目標とするX軸の値

    void Update()
    {
        targetPosX = Mathf.Lerp(transform.position.x, capsule.transform.position.x, Time.deltaTime * 2);    // 線形補間してX軸の値を求める
        transform.position = new Vector3(targetPosX, transform.position.y, transform.position.z); // 線形補間した値をX軸の座標に入れて代入する
    }
}

10行目でMathf.Lerpメソッドを使って、始点をカメラのX座標の値、終点をオブジェクトのX座標の値にして、線形補間する処理を行っています。

補間位置として、ここではフレーム間の時間を計測する変数の「Time.deltaTime」を使っています。

実際にゲームを実行してみると、

オブジェクトが動いてから、少し遅れてカメラの移動が行われているのが分かります。

オブジェクトを滑らかに回転させる処理

最後に、オブジェクトを滑らかに回転させる処理を作ってみます。

以下のキューブ型のオブジェクトを配置して、このオブジェクトをキー操作で左右に回転できるようにスクリプトをアタッチしていきます。

using UnityEngine;

public class Test3 : MonoBehaviour
{
    Quaternion leftQuaternion = Quaternion.AngleAxis(30.0f, Vector3.up);    // 左に回すQuaternion
    Quaternion rightQuaternion = Quaternion.AngleAxis(-30.0f, Vector3.up);  // 右に回すQuaternion

    void Update()
    {
        // Dキー押した場合
        if (Input.GetKeyDown(KeyCode.D))
        {
            transform.rotation = transform.rotation * rightQuaternion;  // 右に回転させる処理
        }
        // Aキー押した場合
        if (Input.GetKeyDown(KeyCode.A))
        {
            transform.rotation = transform.rotation * leftQuaternion;  // 左に回転させる処理
        }
    }
}

5行目と6行目でAngleAxisメソッドを使って、左回転と右回転するQuaternionを作成しています。

そして、13行目でDキーを押したら右に回転、18行目でAキーを押したら左に回転するように、Quaternionを合成してセットしています。

一旦、実行してみると、

上記のように、キー操作でオブジェクトを回転することができていますが、30度ずつ回転することになるので、かくかくと回っています。

この回転が滑らかになるように、スクリプトを修正していきます。

using UnityEngine;

public class Test3 : MonoBehaviour
{
    Quaternion leftQuaternion = Quaternion.AngleAxis(30.0f, Vector3.up);    // 左に回すQuaternion
    Quaternion rightQuaternion = Quaternion.AngleAxis(-30.0f, Vector3.up);  // 右に回すQuaternion
    Quaternion targetQuaternion;  // 目標とするQuaternionを取得する

    void Update()
    {
        // Dキー押した場合
        if (Input.GetKeyDown(KeyCode.D))
        {
            targetQuaternion = transform.rotation * rightQuaternion;    // 目標とするQuaternionに代入する
        }
        // Aキー押した場合
        if (Input.GetKeyDown(KeyCode.A))
        {
            targetQuaternion = transform.rotation * leftQuaternion;    // 目標とするQuaternionに代入する
        }
        transform.rotation = Quaternion.Lerp(transform.rotation, targetQuaternion, Time.deltaTime * 4); // 線形補間したQuaternionを代入
    }
}

14行目と19行目で、DとAキーを押した際に、目標となるQuaternionの値をtargetQuaternionという変数を作ってそれぞれ代入しています。

そして21行目で、Quaternion.Lerpメソッドを使って、始点に自身のrotationの値をセットし、終点に目標となるtargetQuaternionを設定して、線形補間された値をrotationに代入することで、回転処理を行っています。

実際にゲームを実行してみると、

上記のように滑らかにオブジェクトが回転するようになりました。

まとめ

このページでは、UnityのLerpメソッドについて、どんなメソッドなのか、また使い方までをまとめていきましたが、いかがでしたでしょうか?

Lerpとは、2つの点を指定してその直線上の値を近似的に補う線形補間を行うメソッドです。

このLerpメソッドを使うことで、オブジェクトの移動や回転などを滑らかに変化させる処理を行ってくれます。

Lerpメソッドの仕組みは、初めてだと難しい部分がありますが、ゲームに滑らかな処理を作りたい場合には、重要なメソッドになってくるので覚えておきましょう。

最後までお読みいただきまして、ありがとうございました!

コメント