【Unity入門】LerpとSlerpの使い方と違い!自在に補間をかけよう

unityにはLerpやslerpといった、滑らかな回転や移動をするための仕組みが備わっています。この記事では、

  • lerpとslerpとは
  • lerpとslerpの違い
  • lerpとslerpの具体的な使い方

というように、基本的な内容から、少し応用的な内容までわかりやすく解説していきます!

目次

Lerp・Slerpとは

Lerp・Slerpとは二点間を滑らかに移動させるための関数のことです。二点間を補間することによって滑らかに移動させられます。

「補間」について詳しく説明していきましょう。「補間」というのは、例えばAという点があり離れた場所にBという点があった場合、点Aと点Bには間が空いています。その間の数値を近似的に求めることを「補間」と呼びます。

「補間」をすることによりコンピュータは二点間をどのように移動すれば良いかを判断できるようになります。なので、二点間の移動において「補間」は重要なのです!その重要「補間」をunity上で行うのがLerpやSlerpなどの関数です。

二つの違い

それでは「補間」をする関数であるLerpとSlerpはどのような違いがあるのでしょうか?LerpとSlerpには明確な違いがあります。それはLerpは「線形補間」であり、Slerpは「球面線形補間」であるという違いです。

「線形補間」と「球面線形補間」という少し難しい単語が出てきたので、それぞれ説明しておきましょう。

「線形補間」は離れた場所に二点があった場合、その間を直線であることを想定して近似的に補う方法のことです。一方「球面線形補間」は球であることを想定して近似的に補う方法のことです。

文字だけでは少しわかりづらいと思うので実際にやっていきましょう!

Lerpの使い方

基本的な使い方

実際にやっていく前に関数Lerpの基本的な使い方について説明しておきましょう。

Vector3.Lerp(始まりの位置, 終わりの位置, 現在の位置)

関数Lerpは引数を三つとります。一つ目にはVector3型で、始まりの位置。二つ目にはVector3型で、終わりの位置。そして三つ目にはfloat型で、オブジェクトの現在の位置をいれます。

三つ目の現在の位置には0から1までの数字が入り、1が最大です。三つ目の数値が0の場合は始まりの位置が取得され、数値が1の場合は終わりの位が取得されます。数値が0.5の場合は始まりの位置と終わりの位置のちょうど中間になります。

実際に使ってみよう

それでは実際にunity上でやっていきます。まずは始まりの位置と終わりの位置の目印としてオブジェクトを置いておきましょう。オブジェクトはHierarchyの「create」ボタンを押し、「3D Object」、「Sphere」を押すことで作れます。

今回は球体のオブジェクトなので「Sphere」を選択しています。

オブジェクトの名前を私は「startMarker」としておきます。これで始まりの目印オブジェクトが作れたので、複製して終わりの目印オブジェクトを作成しましょう。

複製のやり方は先ほど作ったオブジェクトの上で右クリックをした後に「Duplicate」を選択するとできます。

複製できたら名前を変更してください。私は「EndMarker」と変更しておきます。現時点では二つのオブジェクトの位置が同じになっていますので、少し離しておきましょう。

Scene上でMove Toolを押した後、オブジェクトを選択することで移動させられるようになります。

矢印を操作して、オブジェクトの位置を離したのが下記の画像です。

そのままの状態では「Main Camera」にうまく写り込んでいないと思うので、「Main Camera」の位置を変更して二つのオブジェクトが映るようにしましょう。これで関数Lerpで使う二つの点が作成できました!

今回は二つの点の間の数値を関数Lerpを使って取得していきます。わかりやすくするために取得した数値にオブジェクトをつけて移動させていきます。なので移動させるオブジェクトも作りましょう。先ほどの要領でオブジェクトを作成してください。

名前を「MoveObj」としておきます。動かしたいオブジェクトの位置は始まりの位置オブジェクトと同じにしてください。それではスクリプトを作って、コードを書いていきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    //スタートと終わりの目印
    public Transform startMarker;
    public Transform endMarker;

    // スピード
    public float speed = 1.0F;

    //二点間の距離を入れる
    private float distance_two;

    void Start()
    {
        //二点間の距離を代入(スピード調整に使う)
        distance_two = Vector3.Distance(startMarker.position, endMarker.position);
    }

    void Update()
    {

        // 現在の位置
        float present_Location = (Time.time * speed) / distance_two;

        // オブジェクトの移動
        transform.position = Vector3.Lerp(startMarker.position, endMarker.position, present_Location);
    }
}

上記のコードが書かれたスクリプトを動かしたいオブジェクトに結びつけてください。結びつけた後に「startMarker」と「endendMarker」に対応させたいオブジェクトを設置しましょう。

それでは結果を見てみましょう。

始点から終点へとまっすぐにオブジェクトが動いていますね。これは始点と終点の間の数値を関数Lerpによって取得しているので実現できています。関数Lerpは線形補間ですので、点と点の間には直線があると想定して「補間」しています。

「補間」というのは間を補うことでしたね。簡単にコードの説明をしていきましょう。重要な部分は

  // オブジェクトの移動
        transform.position = Vector3.Lerp(startMarker.position, endMarker.position, present_Location);

transform.positionというのはスクリプトを結びつけたオブジェクトの位置を表しています。今回は動かしたいオブジェクトと結びつけましたね。

関数 Vector3.Lerpの部分では、二点の「線形補間」をしています。一つ目の引数「startMarker.position」には始点の位置情報、二つ目の引数「endMarker.position」には終点の位置情報が入っています。

三つ目の引数「present_Location」には、二点間のどの位置にいるのか0から1までの数字で入っています。「present_Location」の値はUpdate関数の中で実行されてからの時間(Time.time )が入っているので、常に加算されていきます。

「present_Location」の値が0(始点)から1(終点)に変化していくことで、移動できます。また、今回のコードではスピードの値は1.0fになっていますが、この値を変更することで移動する速さを変更できますので、試してみてください。

Slerpの使い方

今度はSlerpの使い方について説明しましょう。引数に関しては先ほどのLerpと同じです。

Vector3.Slerp(始まりの位置, 終わりの位置, 現在の位置)

関数名をLerpからSlerpに変えれば良いだけですね。Slerpを使うと、補間の仕方が「球面線形補間」になり、移動させる場合は軌道が円を描くようになります。

実際に使ってみよう

それではコードを書いていきましょう。先ほどのコードのLerpの部分をSlerpに変えてください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    //スタートと終わりの目印
    public Transform startMarker;
    public Transform endMarker;

    // スピード
    public float speed = 1.0F;

    //二点間の距離を入れる
    private float distance_two;

    void Start()
    {
        //二点間の距離を代入(スピード調整に使う)
        distance_two = Vector3.Distance(startMarker.position, endMarker.position);
    }

    void Update()
    {

        // 現在の位置
        float present_Location = (Time.time * speed) / distance_two;

        // オブジェクトの移動(ここだけ変わった!)
        transform.position = Vector3.Slerp(startMarker.position, endMarker.position, present_Location);
    }
}

出力結果は、

始点から終点へと円を描くように移動していますね。これは「球面線形補間」、点と点の間には円があることを想定して間を補っているからできることです。コードの解説は「Vector3.Slerp」以外同じですので割愛します。

まとめ

いかがでしたか?今回はLerpとslerp[について解説してきました。どちらもオブジェクトを移動させる場合に使いますので、ぜひ覚えてくださいね。

もしLerpとslerpの使い方を忘れてしまったら、この記事を参考にしていただけたら幸いです。

この記事を書いた人

学生時代を含めると、かれこれ10年以上プログラマーとして過ごしています。
様々な言語や環境、プロジェクトに関わってきましたので、より実践的な記事をみなさんにお届きるよう情報発信していきます!

目次