【Unity】SmoothPursuit (滑らか追従) コンポーネントの作り方

Godot 4ゲーム制作 実践ドリル 100本ノック

新品価格
¥1,250から
(2025/12/13 21:27時点)

脱・初心者!Godot 4 ゲーム開発の「2歩目」

新品価格
¥831から
(2025/12/13 21:39時点)

Godot4ローグライク入門 ~ダンジョン自動生成~

新品価格
¥831から
(2025/12/13 21:44時点)

Godot4& GDScriptではじめる 2Dゲーム開発レシピ

新品価格
¥590から
(2025/12/13 21:46時点)

Unityを触り始めた頃、Update() の中に「入力処理」「移動」「カメラ追従」「UI更新」など、全部まとめて書いてしまいがちですよね。動くには動くのですが、少し機能を足したり調整したりするたびに、巨大なスクリプトをスクロールしまくる羽目になります。

特にカメラ処理は「とりあえずプレイヤーの座標に追従させるだけ」と軽く考えて、プレイヤーのスクリプトにべったり書きがちです。すると、

  • プレイヤー以外のオブジェクトに同じ追従処理を使い回せない
  • カメラの挙動を変えるたびにプレイヤーのコードを触ることになる
  • 責務が混ざってテストしづらい

といった問題が出てきます。

そこでこの記事では、「追従する」という機能だけに責務を絞ったコンポーネント 「SmoothPursuit(滑らか追従)」 を作っていきます。カメラにアタッチしてターゲットを指定するだけで、Lerp を使った「少し遅れて追いかける」気持ちいいカメラを実現していきましょう。

【Unity】遅れてヌルっと追いかけるカメラ!「SmoothPursuit」コンポーネント

フルコード


using UnityEngine;

/// <summary>
/// 指定したターゲットの位置へ、Lerp で滑らかに追従させるコンポーネント。
/// 主にカメラ用だが、UIやライトなど「追いかけたいもの」にも使える。
/// </summary>
[DisallowMultipleComponent]
public class SmoothPursuit : MonoBehaviour
{
    [Header("追従ターゲット")]
    [Tooltip("追いかけたい Transform(例: プレイヤーのTransform)")]
    [SerializeField] private Transform target;

    [Header("追従設定")]
    [Tooltip("ターゲットとのオフセット(カメラなら、プレイヤーからどれだけ離すか)")]
    [SerializeField] private Vector3 positionOffset = new Vector3(0f, 5f, -10f);

    [Tooltip("追従のスムーズさ。大きいほど素早く追いかける(推奨: 3〜10)")]
    [SerializeField] private float followSpeed = 5f;

    [Tooltip("特定の軸をロックして追従させない場合に使用(例: 2D横スクロールでZを固定など)")]
    [SerializeField] private bool lockX = false;
    [SerializeField] private bool lockY = false;
    [SerializeField] private bool lockZ = false;

    [Header("初期位置設定")]
    [Tooltip("開始時に現在位置を基準にオフセットを自動計算する")]
    [SerializeField] private bool autoCalculateOffset = false;

    // LateUpdate を使うことで、キャラクターの移動が終わったあとに追従処理を行う
    private void LateUpdate()
    {
        // ターゲットが設定されていない場合は何もしない
        if (target == null)
        {
            return;
        }

        // 追従したい「目標位置」を計算
        Vector3 desiredPosition = target.position + positionOffset;

        // 特定軸をロックしたい場合は、現在位置の値を維持する
        Vector3 currentPosition = transform.position;

        if (lockX)
        {
            desiredPosition.x = currentPosition.x;
        }

        if (lockY)
        {
            desiredPosition.y = currentPosition.y;
        }

        if (lockZ)
        {
            desiredPosition.z = currentPosition.z;
        }

        // Lerp を使って現在位置から目標位置へ滑らかに補間
        // followSpeed に Time.deltaTime を掛けて、フレームレートに依存しない追従速度にする
        float t = followSpeed * Time.deltaTime;

        // Lerp の第3引数は 0〜1 の範囲が基本だが、
        // t が 1 を超えても Mathf.Lerp / Vector3.Lerp 内部でクランプされるので問題はない
        Vector3 smoothedPosition = Vector3.Lerp(currentPosition, desiredPosition, t);

        // 実際に位置を反映
        transform.position = smoothedPosition;
    }

    private void Start()
    {
        // 初期化時にオフセットを自動計算したい場合
        if (autoCalculateOffset && target != null)
        {
            // 現在の自分の位置とターゲットの位置の差分をオフセットとして保存
            positionOffset = transform.position - target.position;
        }
    }

    /// <summary>
    /// 追従ターゲットをコードから動的に差し替えたい場合に使用。
    /// 例: プレイヤーが乗り物に乗ったとき、カメラの注目対象を乗り物に切り替えるなど。
    /// </summary>
    /// <param name="newTarget">新しいターゲットの Transform</param>
    /// <param name="recalculateOffset">オフセットを現在位置から再計算するかどうか</param>
    public void SetTarget(Transform newTarget, bool recalculateOffset = true)
    {
        target = newTarget;

        if (target == null)
        {
            return;
        }

        if (recalculateOffset)
        {
            // 現在の位置から新ターゲットまでの差分をオフセットとして再計算
            positionOffset = transform.position - target.position;
        }
    }

    /// <summary>
    /// 現在のターゲットを取得するためのアクセサ。
    /// 外部からターゲットを確認したいときに利用。
    /// </summary>
    public Transform GetTarget()
    {
        return target;
    }
}

使い方の手順

  1. コンポーネントを作成する
    Unity の Project ビューで右クリック → Create → C# Script を選び、SmoothPursuit という名前で作成します。
    自動生成された中身をすべて削除し、上のフルコードをコピペして保存しましょう。
  2. カメラにアタッチする
    Hierarchy でメインカメラ(例: Main Camera)を選択し、Inspector の「Add Component」ボタンから SmoothPursuit を追加します。
    これでカメラは「追従する能力」を持ったコンポーネントになります。
  3. ターゲットを設定する
    例としてプレイヤーキャラクターを追従させたい場合:
    • Hierarchy からプレイヤーの GameObject(例: Player)を、SmoothPursuitTarget フィールドにドラッグ&ドロップします。
    • カメラの位置をシーンビューで「ちょうどいい位置」に動かし、autoCalculateOffset にチェックを入れておくと、再生開始時にその差分をオフセットとして自動計算してくれます。
    • もしくは、positionOffset を手動で調整(例: (0, 5, -10))してもOKです。
  4. 追従のスピードや軸ロックを調整する
    • followSpeed: 値を大きくするとターゲットに素早く追いつき、小さくすると「ふわ〜っと遅れてついてくる」感じになります。3〜10あたりから試してみると良いですね。
    • lockX / lockY / lockZ: 例えば 2D 横スクロールゲームなら lockY = true, lockZ = true にして、X 方向だけ追従させる、といった使い方ができます。

    プレイヤー以外にも:

    • ボス戦だけ「ボスを中心にカメラを寄せたい」→ ボスの Transform を SetTarget() で設定。
    • 動く床に乗ったときだけ床を追従したい → 床にアタッチしたダミーオブジェクトをターゲットにする。

メリットと応用

SmoothPursuit をコンポーネントとして分離しておくと、

  • 「プレイヤーのロジック」と「カメラの追従ロジック」が完全に分かれるので、どちらかを変更しても相手に影響しにくい
  • プレイヤープレハブを量産しても、カメラ側の設定は変えずに済む
  • レベルデザイン時に「このシーンだけ追従スピードを遅く」「このシーンだけY軸ロック解除」といった調整が、Inspector の数値をいじるだけで完結する
  • カメラ以外にも、ライト・エフェクト・UI など「何かを追いかけたいオブジェクト」にそのまま使い回せる

特にプレハブ管理の観点では、

  • プレイヤー側は「自分がどう動くか」だけに集中したスクリプトにできる
  • カメラ側は「誰をどう追いかけるか」だけを管理するプレハブにできる

という形で責務が分かれ、シーンごとに「このカメラはボスを追う」「このカメラはプレイヤーを追う」といった差し替えも簡単になります。

応用として、例えば「ターゲットから一定距離以上離れたら一気に追いつく」ような挙動を追加するのも面白いです。下記はそのための簡単な改造案です。


    /// <summary>
    /// ターゲットから一定距離以上離れている場合は、瞬時に目標位置へワープさせる例。
    /// 追従がもたつきすぎないようにするセーフティ機構として使える。
    /// </summary>
    /// <param name="maxDistance">これ以上離れていたら即座に追いつく距離</param>
    public void SnapIfTooFar(float maxDistance)
    {
        if (target == null)
        {
            return;
        }

        Vector3 desiredPosition = target.position + positionOffset;
        float distance = Vector3.Distance(transform.position, desiredPosition);

        if (distance > maxDistance)
        {
            // 距離が離れすぎている場合は、Lerp を使わずに一気に目標位置へ移動
            transform.position = desiredPosition;
        }
    }

このように、小さな責務のコンポーネントとして作っておくと、「追従する」という軸でいろいろなバリエーションを積み上げていけます。
巨大なカメラスクリプトを1本育てるよりも、シーンや用途に応じて組み合わせられる小さなコンポーネント群を作っていく方が、長期的にメンテしやすいプロジェクトになりますね。

Godot 4ゲーム制作 実践ドリル 100本ノック

新品価格
¥1,250から
(2025/12/13 21:27時点)

脱・初心者!Godot 4 ゲーム開発の「2歩目」

新品価格
¥831から
(2025/12/13 21:39時点)

Godot4ローグライク入門 ~ダンジョン自動生成~

新品価格
¥831から
(2025/12/13 21:44時点)

Godot4& GDScriptではじめる 2Dゲーム開発レシピ

新品価格
¥590から
(2025/12/13 21:46時点)

URLをコピーしました!