Zenn
💨

【Unity Tips】Unityでなめらかな演出を生むLerpテクニック10選 前編

に公開

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

Lerp(線形補間) は、0~1 の値を用いて2つの状態をスムーズに行き来させる機能です。Unityでは、位置(Vector3) や数値(float)、回転(Quaternion) など、多彩な要素を手軽に補間できるため、アニメーション的な演出やUIのフェードイン/アウトなどに広く活用されています。

たとえば、Mathf.Lerp(a, b, t)は a(開始値)と b(終了値)の間を t(0.0~1.0) で補間する構文です。

• t=0 → aそのまま
• t=1 → bそのまま
• t=0.5 → aとbのちょうど中間の値

この“0から1へ徐々に変化させる”性質を時間経過やプレイヤー操作などと組み合わせれば、位置・回転・スケール・UI透明度などをなめらかに変化させることが可能です。

本記事では、全20個のLerpテクニックのうち、前半10個を詳しく解説します。

サンプルコードは簡易的なものなので、実際のプロジェクトでは変数や処理をカスタマイズしながらご活用ください。

後編はコチラから

https://zenn.dev/ryuryu_game/articles/0626d0db0da13c

Unityの基本操作からC#スクリプトの基礎まで、やさしく学べる入門チュートリアルはこちら
https://zenn.dev/ryuryu_game/books/fd28de9d8e963a/viewer/0570af

1. BGMのフェードイン/アウト

ゲーム開始やシーン切り替え時に、BGMをいきなり鳴らしたり止めたりすると、耳に違和感が生じます。Mathf.LerpAudioSource.volumeを0から1へ徐々に変化させれば、ふんわりと音が立ち上がり、シーン終了時に1から0へゆっくり音量を下げれば、違和感のないフェードアウトが可能です。

ポイント

  • tを時間経過で増やすことで、数秒かけて音量を変更
  • シーンの空気感やイベントの緩急に合わせてBGMをコントロール

サンプルコード

using UnityEngine;

public class BGMFader : MonoBehaviour {
    public AudioSource audioSource;
    public float fadeDuration = 2f;
    private float elapsed = 0f;
    private bool fadeIn = true;

    void Start() {
        audioSource.volume = 0f;
        audioSource.Play();
    }

    void Update() {
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / fadeDuration);
        audioSource.volume = fadeIn ? Mathf.Lerp(0f, 1f, t) : Mathf.Lerp(1f, 0f, t);

        // テスト用:スペースキーでフェードイン/アウト切替
        if (Input.GetKeyDown(KeyCode.Space)) {
            fadeIn = !fadeIn;
            elapsed = 0f;
        }
    }
}

2. 効果音のピッチ変化で新鮮さを演出

同じSEを連打すると耳が飽きてしまいます。Mathf.LerpでAudioSource.pitchを微妙に変化させれば、同じクリップでも毎回少し違う音程になり、新鮮さが維持できます。
跳ねる、殴る、足音など、単純なアクション音に応用可能です。

ポイント:
• 攻撃ごとにt = Random.valueを取得し、pitchをMathf.Lerpで0.9~1.1の間で変化
• 地味な効果ながら、耳疲れを防ぎ、世界が少し動的になる

サンプルコード:

using UnityEngine;

public class SFXPitchRandomizer : MonoBehaviour {
    public AudioSource sfxSource;
    public float pitchMin = 0.9f;
    public float pitchMax = 1.1f;

    void PlaySFX() {
        float t = Random.value;
        sfxSource.pitch = Mathf.Lerp(pitchMin, pitchMax, t);
        sfxSource.PlayOneShot(sfxSource.clip);
    }

    void Update() {
        if (Input.GetKeyDown(KeyCode.F)) {
            PlaySFX();
        }
    }
}

3. エリア移動時の重力変化

特定エリアに入ると重力が軽くなったり、別のエリアでは重くなったりする場合、Vector3.LerpでPhysics.gravityを徐々に変化させると、切り替えが自然に感じられます。
急激な物理変化を避け、プレイヤーは違和感なく新環境に適応できます。

ポイント:
• Gキーなどでエリア変更をトリガー
• 数秒かけて重力ベクトルを補間

サンプルコード:

using UnityEngine;

public class GravityShift : MonoBehaviour {
    public Vector3 normalG = new Vector3(0, -9.81f, 0);
    public Vector3 lowG = new Vector3(0, -2f, 0);
    public float transitionTime = 2f;
    private float elapsed = 0f;
    private bool inLowG = false;

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

        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / transitionTime);
        Physics.gravity = inLowG ? Vector3.Lerp(normalG, lowG, t)
                                 : Vector3.Lerp(lowG, normalG, t);
    }
}

4. パーティクル発生率の段階的変化

イベントが近づくにつれパーティクルが増えたり、戦闘後に徐々に減らしたりするには、Mathf.LerpでParticleSystemのEmission Rateを動的に変更します。
静的な演出から、動きのある「兆し」を表現できるため、プレイヤーをワクワクさせる効果があります。

ポイント:
• Pキーで増減トグル
• Emission率を徐々に上げ下げして、世界が変化している感覚を演出

サンプルコード:

using UnityEngine;

public class ParticleEmissionControl : MonoBehaviour {
    public ParticleSystem pSystem;
    public float startRate = 10f;
    public float endRate = 50f;
    public float changeTime = 3f;
    float elapsed = 0f;
    bool increasing = false;

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

        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / changeTime);
        var emission = pSystem.emission;
        var rateOverTime = emission.rateOverTime;
        rateOverTime.constant = increasing ? Mathf.Lerp(startRate, endRate, t)
                                           : Mathf.Lerp(endRate, startRate, t);
        emission.rateOverTime = rateOverTime;
    }
}

5. デバッグ用パラメータ可変テスト

開発中、「特定の値が増えていくとバグる?」といった調査で、Mathf.Lerpを使って値を徐々に増減させれば、バグ発生の臨界点を探りやすくなります。
あくまでデバッグ用ですが、Lerpはこうした実験的用途にも便利。

ポイント:
• 値を行ったり来たりさせて、一定期間観察
• パラメータの変化による挙動をリアルタイムでチェック可能

サンプルコード:

using UnityEngine;

public class DebugParamLerper : MonoBehaviour {
    public float minVal = 0f;
    public float maxVal = 100f;
    public float cycleTime = 5f;
    float elapsed = 0f;
    bool forward = true;
    public float currentVal = 0f;

    void Update() {
        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / cycleTime);
        currentVal = forward ? Mathf.Lerp(minVal, maxVal, t) : Mathf.Lerp(maxVal, minVal, t);

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

        // ログ出力で観察
        Debug.Log("CurrentVal: " + currentVal);
    }
}

6. エンジン音・風音の変化

乗り物ゲームなどで速度に応じてエンジン音量やピッチをLerpすれば、加速時は徐々に音が高まり、減速時はゆるやかに静まる。
これで「速度感」や「環境変化」を聴覚的にも伝えられ、没入度を高められます。

ポイント:
• t = currentSpeed/maxSpeedで0~1に正規化
• pitchやvolumeをLerpで補間

サンプルコード:

using UnityEngine;

public class EngineSoundController : MonoBehaviour {
    public AudioSource engineAudio;
    public float minPitch = 0.8f;
    public float maxPitch = 1.2f;
    public float maxSpeed = 50f;
    public float currentSpeed = 0f;

    void Update() {
        float t = Mathf.Clamp01(currentSpeed / maxSpeed);
        engineAudio.pitch = Mathf.Lerp(minPitch, maxPitch, t);
    }
}

7. 敵やNPCのふわっとした出現

敵が突然ポップするのではなく、地下からゆっくり浮上するなどVector3.Lerpで登場演出を付ければ、ただの敵出現もイベント的な見せ場に。
怖さや神秘性を表現したいシーンに有効。

ポイント:
• 初期状態でオブジェクトを下方に配置
• 数秒かけてtを増やしながらVector3.Lerpで上昇

サンプルコード:

using UnityEngine;

public class EnemyAppear : MonoBehaviour {
    public Vector3 hiddenPos;
    public Vector3 visiblePos;
    public float appearTime = 1f;
    private float elapsed = 0f;
    private bool appearing = true;

    void Update() {
        if (appearing) {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / appearTime);
            transform.position = Vector3.Lerp(hiddenPos, visiblePos, t);
        }
    }
}

8. メイン・サブメニュー間のスムーズなモード切替

メインメニューからサブメニューへ、RectTransformの位置をLerpで切り替えれば、階層移動が柔らかく感じられます。
UI遷移にメリハリを与え、ユーザーがメニューの深みを直感的に感じ取れます。

ポイント:
• Tabキーなどでモード変更トリガー
• 0.5秒程度で移動すれば、カチカチしたUIから一歩脱却

サンプルコード(概略)

using UnityEngine;

public class MenuSwitcher : MonoBehaviour {
    public RectTransform mainMenu, subMenu;
    public Vector3 mainMenuPos, mainMenuOffPos;
    public Vector3 subMenuPos, subMenuOffPos;
    public float switchTime = 0.5f;
    float elapsed = 0f;
    bool showingSub = false;

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

        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / switchTime);

        mainMenu.anchoredPosition = showingSub ? Vector3.Lerp(mainMenuPos, mainMenuOffPos, t)
                                               : Vector3.Lerp(mainMenuOffPos, mainMenuPos, t);

        subMenu.anchoredPosition = showingSub ? Vector3.Lerp(subMenuOffPos, subMenuPos, t)
                                              : Vector3.Lerp(subMenuPos, subMenuOffPos, t);
    }
}

9. プレイヤー能力値の微細な変化

毒や凍結状態でプレイヤースピードやジャンプ力を一気に変えると違和感が出る。Mathf.Lerpで数秒かけてゆるやかに移行すれば、「徐々に足元が重くなる」「少しずつ滑りやすくなる」など、自然な環境変化をプレイヤーに感じさせられる。

ポイント:
• 状態切替でt=0から開始し、tが1に近づくほど新しいパラメータに近づける
• 急なストレスを回避し、プレイヤーが順応する時間を与える

サンプルコード(スピード変化)

using UnityEngine;

public class PlayerStateAdjust : MonoBehaviour {
    public float normalSpeed = 5f;
    public float poisonSpeed = 2f;
    public float transitionTime = 2f;
    float elapsed = 0f;
    bool poisoned = false;
    float currentSpeed;

    void Start() {
        currentSpeed = normalSpeed;
    }

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

        elapsed += Time.deltaTime;
        float t = Mathf.Clamp01(elapsed / transitionTime);
        currentSpeed = poisoned ? Mathf.Lerp(normalSpeed, poisonSpeed, t)
                                : Mathf.Lerp(poisonSpeed, normalSpeed, t);

        // currentSpeedを移動処理に適用
    }
}

10. 複数Lerpで奏でるゲームクリア演出

シーン終盤、ゲームクリア時に画面のフェード、BGMフェード、報酬アイテム上昇など、複数のLerpを同時進行させれば、調和の取れたフィナーレが演出可能。

ポイント:
• CanvasGroup.alphaで画面フェード
• AudioSource.volumeでBGMフェード
• Vector3.Lerpでアイテムを持ち上げ
• 同じtで全てをコントロールすることで統一感を出す

サンプルコード

using UnityEngine;

public class GameClearSequence : MonoBehaviour {
    public CanvasGroup fadeCanvas;
    public AudioSource bgm;
    public Transform rewardItem;
    public Vector3 startPos, endPos;
    public float duration = 3f;
    float elapsed = 0f;
    bool triggered = false;

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

        if (triggered) {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / duration);
            fadeCanvas.alpha = Mathf.Lerp(0f, 1f, t);
            bgm.volume = Mathf.Lerp(1f, 0f, t);
            rewardItem.position = Vector3.Lerp(startPos, endPos, t);
        }
    }
}

統一された演出で、プレイヤーはフィナーレに心地よい満足感を得られます。

これら後半10個のテクニックでは、Lerpが音、物理挙動、パーティクル、メニュー構造、プレイヤー能力など、より広範な要素に応用可能であることを示しました。

前半で紹介した動きやUIとの組み合わせで、ゲーム内のほぼあらゆる要素をなめらかに変化させ、体験を上質なものにできます。Lerpはシンプルながら柔軟性抜群なので、自分のゲームに合った使い方を見つけてみてください。

この記事を読んでもっと実践したいと感じたあなたへ

Unity開発を効率よく進めるためには、実践的なスキルと仲間との交流が欠かせません。
そんな方におすすめのステップが、下記の3つです。

1. 有料教材「どこでもUnity教室」でゲーム制作を短期マスター

  • 5日でシンプルなFPS完成:初心者向けに要点を押さえたカリキュラム
  • C#や最新のInputSystem、FPS実装まで網羅:つまずきやすいポイントを先回りで解説
  • 購入特典:Discord招待+サンプルプロジェクトDLで、疑問や実装例を即確認

Unity初心者でも最短5日で3D FPSが完成!今すぐ始める入門チュートリアルはこちら

https://zenn.dev/ryuryu_game/books/fd28de9d8e963a/viewer/0570af

2. 無料コミュニティで、疑問をすぐに解消&モチベーションUP

  • 初心者~中級者までOK:学習進度に合わせて質問や情報共有
  • 質問サポートが充実:わからないことを仲間や講師に即相談
  • 学習仲間と切磋琢磨:一緒に学ぶから続けやすい

Discordサーバー参加はこちら

https://discord.gg/5FwuKCacNy

3. 実績豊富な“ゲーム開発所RYURYU”があなたをトータルサポート

  • コナラ総販売200件超:さまざまなUnity開発の依頼を対応
  • VR/AR/AIなど最新技術にも精通:幅広いノウハウを活かして開発支援
  • ゲームクリエイター甲子園や東京ゲームショウなど出展実績多数

ご相談・お問い合わせはこちら

https://coconala.com/users/1772507

Discussion

ログインするとコメントできます