Unityを触り始めた頃、「とりあえず全部Updateに書いちゃえ!」となりがちですよね。移動処理、ジャンプ、ダッシュ、アニメーション、カメラ制御……全部ひとつのスクリプトに詰め込むと、最初は動いていても、あとから仕様変更が入った瞬間に地獄が始まります。

特に「ダッシュ機能」は、

  • 移動速度の一時的な変更
  • クールダウン管理
  • スタミナやエフェクトとの連携

など、他のシステムと絡みやすく、巨大なプレイヤースクリプトの中に埋もれがちな代表例です。

そこでこの記事では、「ダッシュ機能」を単独のコンポーネントとして切り出した DashMechanic を用意して、親オブジェクトの移動速度を一時的に倍増させ、クールダウンもまとめて管理する仕組みを作っていきます。プレイヤーや敵、動く床などにポン付けできるようにしておくと、レベルデザインがかなり楽になりますよ。

【Unity】一時的に爆速!クールダウン付きダッシュ「DashMechanic」コンポーネント

コンポーネントの概要

この DashMechanic コンポーネントは、

  • 親オブジェクトの「通常移動コンポーネント」を参照
  • 入力が来たら、一定時間だけ移動速度を倍率でブースト
  • その後はクールダウンが終わるまで再使用不可

という単機能に絞ったコンポーネントです。

ここでは「親の移動速度」を扱うために、シンプルな移動コンポーネント SimpleMover を一緒に用意し、その moveSpeed をダッシュ中だけ書き換える構成にします。
プロジェクトで既に独自の移動コンポーネントがある場合は、同じような形でプロパティを書き換えるだけで応用できます。


フルコード:SimpleMover + DashMechanic

まずはベースとなる移動コンポーネント SimpleMover と、ダッシュ機能を担当する DashMechanic の2つをまとめて掲載します。どちらも同じゲームオブジェクトにアタッチして使う想定です。


using UnityEngine;
using UnityEngine.InputSystem; // 新Input System用

/// <summary>
/// シンプルな2D/3D共通の移動コンポーネント。
/// - 移動方向(Normalized)と速度をもとに、Transformを移動させる。
/// - 物理挙動が不要なキャラやオブジェクト向け。
/// - DashMechanic から moveSpeed を書き換えられるようにしている。
/// </summary>
public class SimpleMover : MonoBehaviour
{
    [Header("基本移動設定")]
    [SerializeField] private float moveSpeed = 5f; // 通常移動速度
    [SerializeField] private bool useLocalSpace = false; // ローカル座標で移動するか

    // 現在の移動方向(外部から設定)
    private Vector3 moveDirection = Vector3.zero;

    /// <summary>
    /// 外部(Inputなど)から移動方向を設定する。
    /// 正規化はこの中で行う。
    /// </summary>
    public void SetMoveDirection(Vector3 direction)
    {
        // 方向ベクトルを正規化(0ベクトルの場合はそのまま)
        moveDirection = direction.sqrMagnitude > 0.0001f
            ? direction.normalized
            : Vector3.zero;
    }

    /// <summary>
    /// 現在の速度を取得(DashMechanic などから参照する用)。
    /// </summary>
    public float GetMoveSpeed()
    {
        return moveSpeed;
    }

    /// <summary>
    /// 現在の速度を設定(DashMechanic などから一時的に変更する用)。
    /// </summary>
    public void SetMoveSpeed(float newSpeed)
    {
        moveSpeed = Mathf.Max(0f, newSpeed); // マイナス速度は防止
    }

    private void Update()
    {
        if (moveDirection == Vector3.zero) return;

        // 時間依存の移動
        float distance = moveSpeed * Time.deltaTime;

        if (useLocalSpace)
        {
            transform.Translate(moveDirection * distance, Space.Self);
        }
        else
        {
            transform.Translate(moveDirection * distance, Space.World);
        }
    }
}

/// <summary>
/// ダッシュ機能コンポーネント。
/// - 指定された入力アクションが押されたとき、
///   親オブジェクトの SimpleMover の移動速度を一時的に増加させる。
/// - ダッシュ時間とクールダウンを管理する。
/// </summary>
[RequireComponent(typeof(SimpleMover))]
public class DashMechanic : MonoBehaviour
{
    [Header("ダッシュ設定")]
    [SerializeField] private float dashMultiplier = 2f;   // 速度倍率(例: 2倍)
    [SerializeField] private float dashDuration = 0.2f;   // ダッシュ継続時間(秒)
    [SerializeField] private float dashCooldown = 1.0f;   // クールダウン時間(秒)

    [Header("入力設定 (Input System)")]
    [Tooltip("ダッシュ用のInput Action。type=Button 推奨")]
    [SerializeField] private InputActionReference dashActionReference;

    // 内部状態管理
    private SimpleMover simpleMover;
    private float baseMoveSpeed;          // 通常時の速度を保持
    private bool isDashing = false;       // 現在ダッシュ中か
    private bool isOnCooldown = false;    // 現在クールダウン中か
    private float dashTimer = 0f;         // ダッシュ残り時間
    private float cooldownTimer = 0f;     // クールダウン残り時間

    private void Awake()
    {
        // 同じオブジェクトに付いている SimpleMover を取得
        simpleMover = GetComponent<SimpleMover>();
        baseMoveSpeed = simpleMover.GetMoveSpeed();
    }

    private void OnEnable()
    {
        // Input Action の有効化
        if (dashActionReference != null && dashActionReference.action != null)
        {
            dashActionReference.action.performed += OnDashPerformed;
            dashActionReference.action.Enable();
        }
    }

    private void OnDisable()
    {
        // Input Action の無効化
        if (dashActionReference != null && dashActionReference.action != null)
        {
            dashActionReference.action.performed -= OnDashPerformed;
            dashActionReference.action.Disable();
        }
    }

    /// <summary>
    /// ダッシュボタンが押されたときに呼ばれるコールバック。
    /// </summary>
    private void OnDashPerformed(InputAction.CallbackContext context)
    {
        // 既にダッシュ中 or クールダウン中なら無視
        if (isDashing || isOnCooldown) return;

        StartDash();
    }

    /// <summary>
    /// ダッシュ開始処理。
    /// </summary>
    private void StartDash()
    {
        isDashing = true;
        isOnCooldown = true;
        dashTimer = dashDuration;
        cooldownTimer = dashCooldown;

        // 現在の通常速度を記録
        baseMoveSpeed = simpleMover.GetMoveSpeed();

        // 速度を倍率分だけ増加
        float dashedSpeed = baseMoveSpeed * dashMultiplier;
        simpleMover.SetMoveSpeed(dashedSpeed);

        // ここでエフェクトやSEを鳴らしても良い
        // 例: PlayDashEffect();
    }

    /// <summary>
    /// ダッシュ終了処理。
    /// </summary>
    private void EndDash()
    {
        isDashing = false;

        // 速度を元に戻す
        simpleMover.SetMoveSpeed(baseMoveSpeed);
    }

    private void Update()
    {
        // ダッシュ時間のカウントダウン
        if (isDashing)
        {
            dashTimer -= Time.deltaTime;
            if (dashTimer <= 0f)
            {
                EndDash();
            }
        }

        // クールダウン時間のカウントダウン
        if (isOnCooldown)
        {
            cooldownTimer -= Time.deltaTime;
            if (cooldownTimer <= 0f)
            {
                isOnCooldown = false;
            }
        }
    }

    /// <summary>
    /// 現在ダッシュ中かどうかを外部から参照するためのプロパティ。
    /// </summary>
    public bool IsDashing => isDashing;

    /// <summary>
    /// 現在クールダウン中かどうかを外部から参照するためのプロパティ。
    /// </summary>
    public bool IsOnCooldown => isOnCooldown;
}

使い方の手順

① 移動用コンポーネントをセットアップする

まずはプレイヤーや敵など、ダッシュさせたいオブジェクトに SimpleMover をアタッチします。

  1. Hierarchy で「Player」オブジェクトを選択
  2. Add Component から SimpleMover を追加
  3. Move Speed に通常移動速度(例: 5)を設定
  4. 2Dの場合でも3Dの場合でも、SetMoveDirection に渡すベクトル次第で動きます

入力からの移動方向設定は、例えばこんな感じの別コンポーネントに任せるとスッキリします(プレイヤー用の例):


using UnityEngine;
using UnityEngine.InputSystem;

/// <summary>
/// プレイヤー入力を SimpleMover に流し込むだけのコンポーネント。
/// 移動とダッシュを分離することで、責務を小さくしている。
/// </summary>
[RequireComponent(typeof(SimpleMover))]
public class PlayerInputMover : MonoBehaviour
{
    [SerializeField] private InputActionReference moveActionReference;

    private SimpleMover simpleMover;

    private void Awake()
    {
        simpleMover = GetComponent<SimpleMover>();
    }

    private void OnEnable()
    {
        if (moveActionReference != null && moveActionReference.action != null)
        {
            moveActionReference.action.Enable();
        }
    }

    private void OnDisable()
    {
        if (moveActionReference != null && moveActionReference.action != null)
        {
            moveActionReference.action.Disable();
        }
    }

    private void Update()
    {
        if (moveActionReference == null || moveActionReference.action == null) return;

        Vector2 input = moveActionReference.action.ReadValue<Vector2>();

        // 2D横スクロールなら x のみ、3Dなら x,z を使うなど用途に応じて変換
        Vector3 moveDir = new Vector3(input.x, 0f, input.y);

        simpleMover.SetMoveDirection(moveDir);
    }
}

② DashMechanic を追加する

  1. 同じ「Player」オブジェクトに DashMechanic を追加
  2. インスペクターで以下を設定
    • Dash Multiplier: 2(2倍速ダッシュ)
    • Dash Duration: 0.2(0.2秒だけブースト)
    • Dash Cooldown: 1(1秒ごとにダッシュ可)

③ Input System の設定(ダッシュボタン)

Unity の新 Input System を使って、ダッシュ用のアクションを用意します。

  1. Project ウィンドウで Input Actions アセット(例: PlayerInputActions.inputactions)を開く
  2. 「Player」アクションマップに Dash というアクションを追加
  3. Action Type を Button に設定
  4. Binding にキーボードの LeftShift やゲームパッドの Bボタン などを割り当て
  5. アセットを保存
  6. Hierarchy で適当なオブジェクト(または Player)に PlayerInput を追加し、先ほどのアセットを割り当て
  7. DashMechanic の Dash Action Reference に、Input Actions アセット内の Dash アクションをドラッグ&ドロップ

④ 実際の使用例

  • プレイヤーキャラクター
    横スクロールアクションで、プレイヤーに SimpleMover + PlayerInputMover + DashMechanic をアタッチ。
    左右キーで移動し、Shift で一瞬だけスピードアップさせることで、敵の攻撃を避けるアクションが簡単に実装できます。
  • 敵キャラクター
    敵AIがプレイヤーとの距離を詰めるときだけ DashMechanicStartDash() をスクリプトから呼び出すことで、突進攻撃のような挙動を実装可能です(AI側スクリプトから public bool IsOnCooldown を見て使用タイミングを制御すると良いです)。
  • 動く床(ギミック)
    通常はゆっくり動く床に SimpleMover を付けておき、プレイヤーが乗った瞬間に DashMechanic をトリガーすることで、「一瞬だけ加速するベルトコンベア」などのギミックを作ることもできます。

メリットと応用

コンポーネント分割のメリット

DashMechanic を独立コンポーネントにしておくと、次のようなメリットがあります。

  • プレイヤースクリプトが肥大化しない
    移動、ダッシュ、ジャンプ、攻撃をそれぞれ別コンポーネントに分けておけば、どれか1つを改造しても他に影響しづらくなります。ダッシュの仕様変更(倍率・時間・クールダウンなど)も DashMechanic だけを見れば良いので、デバッグが楽です。
  • プレハブの再利用性が高い
    「この敵にもダッシュさせたい」となったとき、DashMechanic をアタッチして、AIスクリプトからトリガーするだけでOK。プレイヤーと敵で同じダッシュロジックを共有できます。
  • レベルデザイン時にパラメータ調整が簡単
    シーン上のオブジェクトごとに Dash MultiplierDash Cooldown をバラバラに設定できるので、「このステージだけダッシュが強い」「この敵だけクールダウンが短い」といった調整がインスペクターから直感的にできます。

改造案:スタミナ制限付きダッシュ

もう一歩踏み込むと、「スタミナが一定以上ないとダッシュできない」という制限を入れることもできます。
下記は DashMechanic に追加するイメージのメソッド(スタミナ値は外部から渡される想定)です。


/// <summary>
/// 外部からスタミナ値を受け取り、
/// 足りない場合はダッシュを拒否する例。
/// (DashMechanic 内に追加して使う)
/// </summary>
public bool TryStartDashWithStamina(float currentStamina, float requiredStamina)
{
    // すでにダッシュ中 or クールダウン中なら失敗
    if (isDashing || isOnCooldown) return false;

    // スタミナが足りなければ失敗
    if (currentStamina < requiredStamina) return false;

    // ここで外部のスタミナ管理コンポーネントに消費を依頼しても良い
    // 例: staminaComponent.Consume(requiredStamina);

    StartDash();
    return true;
}

このように、ダッシュ自体のロジックは DashMechanic に閉じ込めつつ、スタミナ管理やAI制御などは別コンポーネントに分けて連携させると、責務が明確でメンテナンスしやすいプロジェクトになります。
Update に全部書きがちな処理こそ、どんどんコンポーネントに分割していきましょう。