Unityを触り始めた頃にありがちなのが、プレイヤーの移動、カメラ制御、ギミックの回転、UI更新…とにかく全部をひとつの Update() に書いてしまうパターンですね。
動けば最初は嬉しいのですが、時間が経つにつれて「どこを直せばいいかわからない」「別シーンでも使いたいのにコピペ地獄」という状態になりがちです。

そこで役立つのが、小さな責務ごとに分けたコンポーネント指向の設計です。
この記事では「指定したオブジェクト(多くは足場やギミック)を、一定の速度で回転させ続ける」だけに責務を絞ったコンポーネント 「AutoRotator」 を作っていきます。

回転ギミックを使い回したいときに、プレイヤー制御スクリプトに手を入れる必要はありません。
回したいオブジェクトにこのコンポーネントをポンと付けるだけで、どのシーンでも同じ動きを再利用できるようにしていきましょう。

【Unity】回転ギミックを量産しよう!「AutoRotator」コンポーネント

フルコード(C# / MonoBehaviour)


using UnityEngine;

/// <summary>
/// 指定したTransformを、指定した軸・速度で回転させ続けるコンポーネント。
/// - 足場、トラップ、オブジェクトの飾り回転などに利用可能。
/// - 自分自身を回すことも、親オブジェクトなど別のTransformを回すことも可能。
/// </summary>
public class AutoRotator : MonoBehaviour
{
    // 回転させる対象。未指定の場合はこのコンポーネントが付いているGameObject自身を回す
    [SerializeField]
    private Transform targetTransform;

    // 1秒あたりの回転量(度)。XYZそれぞれの軸ごとに設定可能
    [SerializeField]
    private Vector3 rotationSpeed = new Vector3(0f, 90f, 0f);

    // ワールド座標系で回転させるかどうか。falseならローカル座標系で回転
    [SerializeField]
    private bool useWorldSpace = false;

    // ゲーム開始時に自動で回転を有効にするか
    [SerializeField]
    private bool autoStart = true;

    // 一時停止用フラグ(外部スクリプトやインスペクタから制御可能)
    [SerializeField]
    private bool isRotating = true;

    // --- プロパティ(読み取り専用) ---
    public bool IsRotating => isRotating;

    private void Reset()
    {
        // コンポーネントを追加したときに、自身のTransformを自動セット
        targetTransform = transform;
        rotationSpeed = new Vector3(0f, 90f, 0f);
        useWorldSpace = false;
        autoStart = true;
        isRotating = true;
    }

    private void Awake()
    {
        // targetTransform が未設定なら自分自身を対象にする
        if (targetTransform == null)
        {
            targetTransform = transform;
        }
    }

    private void Start()
    {
        // autoStart が false の場合は開始時に停止状態にしておく
        if (!autoStart)
        {
            isRotating = false;
        }
    }

    private void Update()
    {
        // 回転が無効なときは何もしない
        if (!isRotating || targetTransform == null)
        {
            return;
        }

        // 経過時間を考慮して、フレームレートに依存しない回転量を計算
        Vector3 deltaRotation = rotationSpeed * Time.deltaTime;

        // ローカル回転かワールド回転かを選択
        if (useWorldSpace)
        {
            // ワールド座標系での回転
            targetTransform.Rotate(deltaRotation, Space.World);
        }
        else
        {
            // ローカル座標系での回転
            targetTransform.Rotate(deltaRotation, Space.Self);
        }
    }

    /// <summary>
    /// 回転を開始(再開)する。
    /// 外部スクリプトやUIボタンから呼び出せるようにpublicにしている。
    /// </summary>
    public void StartRotation()
    {
        isRotating = true;
    }

    /// <summary>
    /// 回転を一時停止する。
    /// </summary>
    public void StopRotation()
    {
        isRotating = false;
    }

    /// <summary>
    /// 回転速度を変更する。
    /// 例: ギミックの難易度を上げたいときに呼び出す。
    /// </summary>
    /// <param name="newSpeed">新しい回転速度(度/秒)</param>
    public void SetRotationSpeed(Vector3 newSpeed)
    {
        rotationSpeed = newSpeed;
    }

    /// <summary>
    /// 回転対象のTransformを動的に差し替える。
    /// 例: ゲーム中に別の足場を回すように変更したい場合など。
    /// </summary>
    public void SetTarget(Transform newTarget)
    {
        targetTransform = newTarget != null ? newTarget : transform;
    }
}

使い方の手順

ここでは具体的な例として、

  • プレイヤーが乗る「回転足場」
  • 当たるとダメージを受ける「回転トゲ付きポール」
  • ただの見た目用「回転コイン」

といったオブジェクトに適用するケースを想定して説明します。

手順①:回転させたいオブジェクトを用意する

  • Hierarchy で Right Click > 3D Object > Cube などを作成し、「RotatingPlatform」など分かりやすい名前にします。
  • プレイヤーが乗る足場にしたい場合は、サイズを調整して床っぽい形にしておきます。
  • ポールやコインなど別のオブジェクトでも同様です。Prefab にしておくと後で量産しやすいです。

手順②:「AutoRotator」コンポーネントを追加する

  • 回転させたいオブジェクトを選択します(例: RotatingPlatform)。
  • Inspector の Add Component ボタンを押し、「AutoRotator」と検索して追加します。
  • Reset() により、targetTransform には自動で自分自身がセットされます。

この状態でプレイすると、デフォルト設定では「ローカルY軸を毎秒90度」で回転し続けます。
床オブジェクトなら、ぐるぐる回転する足場の完成です。

手順③:回転の向き・速度を調整する

Inspector 上で、以下のパラメータを調整してギミックの性格を変えられます。

  • Target Transform
    デフォルトでは自分自身(このコンポーネントが付いているオブジェクト)。
    親の足場だけを回しつつ、子オブジェクト(エフェクトなど)は別制御にしたい場合などは、明示的に別の Transform をドラッグ&ドロップで指定しましょう。
  • Rotation Speed
    (x, y, z) それぞれの軸の回転速度(度/秒)。
    例:
    • 回転足場: (0, 45, 0)
    • 横方向に倒れ続ける棒: (0, 0, 60)
    • 3軸同時にグルグル回るトゲ: (30, 60, 90)
  • Use World Space
    • OFF(デフォルト): ローカル軸で回転。オブジェクトの向きに沿って回転します。
    • ON: ワールド軸で回転。例えば常に「世界のY軸」を中心に回したい場合はこちら。
  • Auto Start
    • ON: ゲーム開始と同時に回転開始。
    • OFF: 最初は止まった状態。トリガーやボタンで StartRotation() を呼ぶまで静止させたい場合に便利。
  • Is Rotating
    実行中でもチェックを外したり付けたりすることで、一時停止/再開を確認できます。
    スクリプトからは StartRotation() / StopRotation() を呼び出すのが基本です。

手順④:ゲーム進行に応じて回転を制御する(発展)

少し踏み込んだ使い方として、例えば「スイッチを押したら足場が回転し始める」ギミックを作ることもできます。


using UnityEngine;

public class RotationSwitch : MonoBehaviour
{
    [SerializeField]
    private AutoRotator targetRotator;

    private void OnTriggerEnter(Collider other)
    {
        // プレイヤーがスイッチに触れたら回転開始
        if (other.CompareTag("Player") && targetRotator != null)
        {
            targetRotator.StartRotation();
        }
    }

    private void OnTriggerExit(Collider other)
    {
        // 離れたら止める例(必要なければ削除してOK)
        if (other.CompareTag("Player") && targetRotator != null)
        {
            targetRotator.StopRotation();
        }
    }
}

このように、回転そのもののロジックは AutoRotator に閉じ込めておき、
「いつ回すか」「どのくらいの速度にするか」といった制御だけを別コンポーネントに任せると、責務がきれいに分離できます。

メリットと応用

AutoRotator を導入するメリットは、単に「回転する」以上に、プロジェクト全体の設計がスッキリする点にあります。

  • プレハブ化が簡単
    回転足場、回転トゲ、回転コインなどをそれぞれ Prefab にしておけば、
    シーン上にドラッグ&ドロップするだけで同じ挙動を使い回せます。
    速度や軸を変えたいときも、Prefab のインスタンス側でパラメータを変えるだけでOKです。
  • レベルデザインの試行錯誤がしやすい
    「この足場はもう少しゆっくり」「このトゲはもっと速く」など、
    デザイナーや自分自身がシーンビュー上でパラメータをいじるだけで調整できます。
    スクリプトを開いて書き換える必要がないので、試行錯誤が高速になります。
  • 責務が明確でテストしやすい
    「回転の挙動」だけをこのコンポーネントが担当しているので、
    バグが出たときも AutoRotator だけを確認すればよく、原因の切り分けがしやすくなります。
  • 他のコンポーネントと組み合わせやすい
    ダメージ判定、サウンド再生、エフェクトなどは別コンポーネントとして付け足すだけでOKです。
    「回転ロジック」と「ゲームルールロジック」が混ざらないので、Godクラス化を防げます。

改造案:ゆっくり加速しながら回転させる

例えば「ゲーム開始直後はゆっくり、数秒かけて最大速度まで加速する」ようなギミックを作りたい場合、
以下のようなメソッドを AutoRotator に追加して、外部からコルーチンを呼び出す形にしても面白いです。


    /// <summary>
    /// 一定時間かけて回転速度を変化させる(線形補間)。
    /// 例: StartCoroutine(autoRotator.LerpSpeed(new Vector3(0, 180, 0), 3f));
    /// </summary>
    public System.Collections.IEnumerator LerpSpeed(Vector3 targetSpeed, float duration)
    {
        Vector3 startSpeed = rotationSpeed;
        float elapsed = 0f;

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / duration);

            // 線形補間で速度をなめらかに変化させる
            rotationSpeed = Vector3.Lerp(startSpeed, targetSpeed, t);

            yield return null;
        }

        // 最終的に目標速度で固定
        rotationSpeed = targetSpeed;
    }

ゲーム開始時に StartCoroutine(autoRotator.LerpSpeed(...)) を呼び出せば、
じわじわ難易度が上がっていく回転足場なども簡単に作れます。
このように、小さなコンポーネントをベースに「ちょい足し」していくスタイルで、柔軟なギミックを量産していきましょう。