👌

Unityでなめらかな演出を生むLerpテクニック10選

2024/12/21に公開

Unityでなめらかな演出を生むLerpテクニック10選

Lerp(線形補間)は、0~1の値を用いて2つの状態をスムーズに行き来する機能で、Unity内で手軽にさまざまな演出を実現できます。本記事では、前回挙げた20個のテクニックのうち、前半10個をさらに

詳しく解説し、簡易的なサンプルコードも示します。
あくまでサンプルなので、実際にはプロジェクトに合わせて変数や処理をカスタマイズしてください。

基本的な考え方

Lerpはtが0のとき開始値、1のとき終了値、0.5のとき中間値を返します。

tを時間経過などで徐々に変化させることで、位置・回転・数値・UI表示などをなめらかに変えることが可能です。

1. オブジェクトのなめらかな移動

シーン開始時、キャラクターが初期位置から目的位置へゆっくり移動する場面を考えます。
Vector3.Lerpを使えば、オブジェクトがふわっと移動して「登場」する演出が可能です。

サンプルコード:

using UnityEngine;

public class SmoothMover : MonoBehaviour {
    public Vector3 startPos;
    public Vector3 endPos;
    public float duration = 2f; // 2秒かけて移動
    private float elapsed = 0f;

    void Start() {
        transform.position = startPos;
    }

    void Update() {
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / duration);
        transform.position = Vector3.Lerp(startPos, endPos, t);
    }
}

この例では、ゲーム開始後2秒かけてstartPosからendPosへとオブジェクトがなめらかに移動します。

2. プレイヤー追従カメラ

カメラがプレイヤーを急に追いかけると、画面がガクガクして不自然。Vector3.Lerpでカメラ位置を少し遅れて追従させ、安定感を出しましょう。

サンプルコード:

using UnityEngine;

public class FollowCamera : MonoBehaviour {
    public Transform player;
    public float followSpeed = 0.1f; // 小さい値ほど追従が遅い
    private Vector3 offset;

    void Start() {
        offset = transform.position - player.position;
    }

    void LateUpdate() {
        Vector3 targetPos = player.position + offset;
        transform.position = Vector3.Lerp(transform.position, targetPos, followSpeed);
    }
}

t代わりにfollowSpeedを固定値で使用していますが、基本原理は同じ。transform.positionが毎フレーム、プレイヤー位置へ近づくため、ふわっとした追従感が得られます。

3. カメラズームの調整

シーン内の状況に応じてカメラをズームイン・アウトしたいとき、Mathf.LerpでCamera.fieldOfView(FOV)を変化させると急な変化を回避できます。

サンプルコード:

using UnityEngine;

public class CameraZoom : MonoBehaviour {
    public Camera mainCam;
    public float normalFOV = 60f;
    public float zoomedFOV = 30f;
    public float zoomTime = 1f; // 1秒かけてズーム
    private float elapsed = 0f;
    private bool zoomingIn = false;

    void Update() {
        if (Input.GetKeyDown(KeyCode.Z)) {
            zoomingIn = !zoomingIn;
            elapsed = 0f;
        }

        if (zoomingIn) {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / zoomTime);
            mainCam.fieldOfView = Mathf.Lerp(normalFOV, zoomedFOV, t);
        } else {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / zoomTime);
            mainCam.fieldOfView = Mathf.Lerp(zoomedFOV, normalFOV, t);
        }
    }
}

Zキーでズームイン・アウトを切り替え、1秒かけてFOVが変化するため、スムーズなカメラコントロールが可能。

4. UIパネルのスライドイン・アウト

メニューやポップアップウィンドウを、画面外からスライドさせて表示すると、より洗練されたUIに感じられます。

サンプルコード:

using UnityEngine;

public class UISlide : MonoBehaviour {
    public RectTransform panel;
    public Vector3 hiddenPos = new Vector3(-500,0,0);
    public Vector3 visiblePos = new Vector3(0,0,0);
    public float slideTime = 0.5f;
    private float elapsed = 0f;
    private bool showing = false;

    void Start() {
        panel.anchoredPosition = hiddenPos;
    }

    void Update() {
        if (Input.GetKeyDown(KeyCode.M)) {
            showing = !showing;
            elapsed = 0f;
        }

        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / slideTime);
        Vector3 current = showing ? Vector3.Lerp(hiddenPos, visiblePos, t) : Vector3.Lerp(visiblePos, hiddenPos, t);
        panel.anchoredPosition = current;
    }
}

Mキーでメニュー表示をトグルする例。
パネルが左端からスライドイン・アウトするため、ユーザーは自然な画面遷移を感じられます。

5. スコア数値のアニメーション

スコアが増えたとき、一瞬で数字を切り替えるより、Mathf.Lerpで中間値を出して数字を段階的に更新すれば、数字がすーっと伸びるアニメーションが可能です。

サンプルコード:

using UnityEngine;
using UnityEngine.UI;

public class ScoreAnimator : MonoBehaviour {
    public Text scoreText;
    private int currentScore = 0;
    private int targetScore = 0;
    public float increaseTime = 0.5f;
    private float elapsed = 0f;

    void Update() {
        if (Input.GetKeyDown(KeyCode.Space)) {
            // スペース押すたびに+100点加算
            targetScore += 100;
            elapsed = 0f;
        }

        if (currentScore != targetScore) {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / increaseTime);
            int displayedScore = (int)Mathf.Lerp(currentScore, targetScore, t);
            scoreText.text = displayedScore.ToString();

            if (t >= 1f) {
                currentScore = targetScore;
            }
        }
    }
}

スコアがゆっくり加算され、プレイヤーは達成感をじわじわ味わえる。

6. ミニマップアイコンの追従

ミニマップ上のアイコンが対象にべったり貼り付くより、Vector3.Lerpで遅れをもって追うと画面表示が自然になります。

ポイント:
メインカメラやプレイヤーの位置を参考にアイコン位置を計算し、それをLerpで更新します。

サンプルコード:

using UnityEngine;

public class MinimapIcon : MonoBehaviour {
    public Transform target; // プレイヤーなど追う対象
    public float followSpeed = 0.1f;

    void LateUpdate() {
        Vector3 targetPos = target.position;
        transform.position = Vector3.Lerp(transform.position, targetPos, followSpeed);
    }
}

t相当はfollowSpeedとして固定値を使用していますが、本質は同じ。アイコンが滑らかに付いていくため、ミニマップがわずかに遅れて反応し、動きに生気が出ます。

7. UIゲージの滑らかな変動

HPやスタミナバーなど、ゲージが瞬時に更新されると無機質な印象。Mathf.Lerpで現在値と目標値の中間値を出し、徐々にゲージを伸縮させると、ダメージの重みや回復の喜びを間接的に伝えられます。

サンプルコード:

using UnityEngine;
using UnityEngine.UI;

public class SmoothGauge : MonoBehaviour {
    public Image gaugeFill; // Imageタイプ:fillAmountで0~1を指定
    private float currentFill = 1f;
    private float targetFill = 1f;
    public float adjustSpeed = 2f;

    void Update() {
        if (Input.GetKeyDown(KeyCode.D)) {
            // ダメージ:ゲージ減らす(例:10%減)
            targetFill = Mathf.Clamp01(targetFill - 0.1f);
        }

        currentFill = Mathf.Lerp(currentFill, targetFill, Time.deltaTime * adjustSpeed);
        gaugeFill.fillAmount = currentFill;
    }
}

時間経過でtを擬似的に表現している例。ゲージがスムーズに減少し、ゲーム体験がより自然になる。

8. タイトルロゴのフェードイン

タイトル画面でロゴが不意に表示されるより、CanvasGroup.alphaをMathf.Lerpで0→1にすると、ロゴがふんわり浮かび上がる。最初のインパクトがソフトになり、プレイヤーに穏やかなスタートを提供。

サンプルコード:

using UnityEngine;

public class TitleFade : MonoBehaviour {
    public CanvasGroup titleCanvasGroup;
    public float fadeInTime = 1f;
    private float elapsed = 0f;

    void Start() {
        titleCanvasGroup.alpha = 0f;
    }

    void Update() {
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / fadeInTime);
        titleCanvasGroup.alpha = Mathf.Lerp(0f, 1f, t);
    }
}

ロゴが徐々に明瞭になることで、シーン開始時の印象がまるで映画のオープニングのように上品になる。

9. パネルの回転アニメーション

イベント発生時、画面上のパネルをQuaternion.Lerpでゆっくり回転させ、一度傾いてから元に戻すと、ちょっとした注目効果を生み出せる。

サンプルコード:

using UnityEngine;

public class PanelRotate : MonoBehaviour {
    public float rotateAngle = 15f;
    public float rotateTime = 0.5f;
    private float elapsed = 0f;
    private bool triggered = false;

    Quaternion originalRot;
    Quaternion tiltedRot;

    void Start() {
        originalRot = transform.rotation;
        tiltedRot = originalRot * Quaternion.Euler(0,0,rotateAngle);
    }

    void Update() {
        if (Input.GetKeyDown(KeyCode.R)) {
            triggered = !triggered;
            elapsed = 0f;
        }

        if (triggered) {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / rotateTime);
            transform.rotation = Quaternion.Lerp(originalRot, tiltedRot, t);
        } else {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / rotateTime);
            transform.rotation = Quaternion.Lerp(tiltedRot, originalRot, t);
        }
    }
}

こうした小さなモーションが、プレイヤーの注目をそのパネルに集めるのに役立つ。

10. 背景要素の動的シフト

背景の雲や遠景オブジェクトをわずかに移動させると、ゲーム世界に「風が吹いている」ような微妙な変化を付与できる。

Vector3.Lerpで位置を行ったり来たりさせれば、画面が静止画的でなくなり、プレイヤーは背景のわずかな動きから「生きた世界」を感じる。

サンプルコード:

using UnityEngine;

public class BackgroundShift : MonoBehaviour {
    public Vector3 posA;
    public Vector3 posB;
    public float cycleTime = 5f;
    private float elapsed = 0f;
    private bool forward = true;

    void Update() {
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / cycleTime);

        if (forward)
            transform.position = Vector3.Lerp(posA, posB, t);
        else
            transform.position = Vector3.Lerp(posB, posA, t);

        if (t >= 1f) {
            forward = !forward;
            elapsed = 0f;
        }
    }
}

この例では、オブジェクトがposAとposBを往復して、背景にわずかな有機的な動きを与える。

まとめ

ここまで紹介した10個のテクニックでは、Lerpを用いて動きやUI、カメラ、数値表示など、多岐にわたる要素をなめらかに変化させる方法を示しました。
ポイントは「瞬間的な変化」を「段階的な変化」に置き換えることで、プレイヤーに優しく自然な印象を与えることです。

この考え方はあらゆる要素に応用でき、ゲームをより洗練されたものにしてくれます。初心者のうちはまず簡単なLerpを試し、慣れてきたら2D→3D、UI→サウンド、物理挙動など、様々な領域でLerpを活用し、独自の演出や快適な操作感を生み出してみてください。


Unityをもっと学びたい“あなた”へ 『どこでもUnity教室』

Unityを独学しているけれど、情報収集に時間がかかり、孤独や不安を感じていませんか?
「どこでもUnity教室」は、そんなあなたのために作られたオンライン学習コミュニティです。

初心者から中級者までを対象に、独学では難しいスキル習得をサポートします。
講師や仲間と一緒に学びながら、分からないことはすぐに解決できる環境をご用意しました。
孤独や情報過多の不安を解消し、効率よく次のステップへ進みましょう!

どこでもUnity教室の特徴

  • 無料で気軽に始められる!
    初心者も中級者も歓迎!仲間と一緒に学びましょう。

  • 作業通話ができるボイスチャンネル
    独学の孤独を解消して、効率よく学べます。

  • すぐに質問できる安心サポート
    質問を投稿すればすぐに解決!他の参加者や講師が迅速に対応します。

  • オンライン教材を順次公開予定
    実践的な課題でスキルを磨ける教材が続々登場します。

独学に限界を感じていませんか?

ChatGPTやインターネットを使えば情報は簡単に手に入りますが、それだけでは「知っているけどできない」第2段階で止まってしまいます。

スキル習得の「第2段階」とは?

「第2段階」は、自分の弱点を認識する重要なステップです。この段階では、

  • 「やりたいことがわかるけど、どう実現するかわからない」
  • 「スクリプトを書いてみたけど、うまく動かない」
    といった悩みに直面します。

「どこでもUnity教室」で第2段階を突破!

「どこでもUnity教室」は、あなたが第2段階を効率よく突破し、次のステップに進むための環境を提供します:

  • 質問しやすい環境:気軽に質問して、すぐに問題を解決!
  • 安心の実践課題:失敗を恐れず挑戦できるステップアップ型の課題。
  • 的確なフィードバック:つまずきポイントを明確にして次のステップへ!(有料プラン予定)

無料で始められるので、まずは参加して学びを加速させましょう!

参加はこちら!

「どこでもUnity教室」Discordサーバーは2024年12月2日スタート!
無料で参加できるこの機会をお見逃しなく!

❏ Discordサーバーに参加する ❏

https://discord.gg/5FwuKCacNy

一人で悩む必要はありません。あなたの成長を全力でサポートする仲間と環境が、ここにあります!

Discussion