💨

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

2024/12/21に公開

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をもっと学びたい“あなた”へ 『どこでもUnity教室』

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

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

どこでもUnity教室の特徴

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

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

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

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

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

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

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

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

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

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

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

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

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

参加はこちら!

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

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

https://discord.gg/5FwuKCacNy

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

Discussion