【Unity】動く床の作り方!アクションゲームでよくある仕掛けを作ってみよう

動く床の作り方 ゲーム開発

Unityでアクションゲーム等を作っていると「動く床」を実装したくなる場合があります。これは一見すると簡単に実装できそうな気がするのですが、実は意外と難しくて何も考えずに作ると

床が動いたとき、上に乗っているキャラクターはそのまま動かず滑り落ちてしまう

という問題が発生してしまいます(下のツイートのような感じ)。

なので初心者の方にとっては実装が悩ましいギミックの一つなのではないでしょうか。

そこでここでは「キャラクターが滑り落ちずに一緒に移動する動く床」の作り方を解説していきますね。

動作サンプル

まず、はじめに動く床の動作サンプルを掲載します。次のGIFをご覧ください。

Unity 動く床の例

(画像クリックでGIF再生)

床が動くとキャラクターも一緒に移動しているのが分かりますね。今回はこのような動く床を作ってみましょう。

動く床の作り方

2通りある実装方法の比較

では次は気になる作り方についてですが、このような動く床を実装する方法は大きく分けて2通りあります。

  1. キャラクターが床の上に乗っている間だけ、キャラクターを床の子オブジェクトにする方法
  2. キャラクターが床の上に乗っている間、キャラクターのRigidbodyに力を加える方法

一つ目はキャラクターを一時的に床の子オブジェクトにすることでTransform的に床と一緒に移動させるやり方、二つ目はキャラクターのRigidbodyにAddForceすることで床とキャラクターの移動を合わせるやり方となります。

両者を比較すると1番目のほうが簡単に実装できます。ただし1番目の方法は

  • 床のスケールをいじっている場合、キャラクターが床に乗った時にキャラクターのスケールがおかしくなってしまうことがある
  • 床が動いている時にキャラクターを動かすとガタガタとした動きになってしまうことがある

といった問題が発生することも多くあまりお勧めできないやり方です。そこで若干手間ではありますが今回は2番目の「Rigidbodyに力を加える方法」を採用することにします(※注)。


※注:当然ながらRigidbodyを使っていないキャラクター(CharacterControllerやNavmeshAgent等を使って移動を制御する場合)には使えないのでご注意ください。

トリガーの設定

さて今回のような動く床を作るにあたっては「上面にキャラクターが乗っているかどうか」を判定する必要があります。この処理のやり方はいくつか考えられますが、ここでは一番簡単なトリガーを使う方法を試してみましょう。

まずは床のゲームオブジェクトにRigidbodyとコライダーをアタッチし、Rigidbodyの「Is Kinematic」にチェックを入れておきます。そうしたら次に下の図のように床の上面に薄いコライダーを用意して「トリガーにする」にチェックを入れておいてください。

動く床のトリガーの例

これで下準備は完了です。

動く床のC#スクリプト

では動く床を制御するためのC#スクリプトを掲載します。

注意:下記のスクリプトは自由に使っていただいて構いませんが、作者を偽るのは禁止です。例えば別の場所に掲載する場合は必ずクレジットを明記してください。
using System.Collections.Generic;
using UnityEngine;

public class MovingPlatform : MonoBehaviour
{

    [Header("必要なコンポーネントを登録")]
    [SerializeField]
    Rigidbody rigidBody = null;

    [Header("基本設定")]
    [SerializeField]
    Vector3 speed = Vector3.zero;

    List<Rigidbody> rigidBodies = new();

    void FixedUpdate()
    {
        MovePlatform();
        AddVelocity();
    }

    void OnTriggerEnter(Collider other)
    {
        rigidBodies.Add(other.gameObject.GetComponent<Rigidbody>());
    }

    void OnTriggerExit(Collider other)
    {
        rigidBodies.Remove(other.gameObject.GetComponent<Rigidbody>());
    }

    void MovePlatform()
    {
        rigidBody.MovePosition(transform.position + Time.fixedDeltaTime * speed);
    }

    void AddVelocity()
    {
        if (rigidBody.velocity.sqrMagnitude <= 0.01f)
        {
            return;
        }

        for (int i = 0; i < rigidBodies.Count; i++)
        {
            rigidBodies[i].AddForce(rigidBody.velocity, ForceMode.VelocityChange);
        }
    }

}

C#スクリプトの解説

シンプルなC#スクリプトなのでコードを追ってもらったほうが理解しやすいと思いますが、ザックリ解説しておくと次のような処理内容となっています。

  • FixedUpdate関数内
    →床の移動処理と、床に乗っているゲームオブジェクトへの速度加算処理
  • OnTriggerEnter関数内
    →床に乗ったゲームオブジェクトのRigidbodyをリストに追加
  • OnTriggerExit関数内
    →床から離れたゲームオブジェクトのRigidbodyをリストから削除

なお、ここでは床の動きはspeed変数に指定した分だけ直線移動し続けるという単純な移動方法となっています。もし往復移動させたいといった場合は適宜改造してください。

おわりに

以上、簡単ではありますが動く床の作り方をご紹介しました。

動く床はアクションゲームではほぼ必須と言っても過言ではないくらいよくある仕掛けなので、作り方を知っておくと便利です。ぜひ上記の内容を参考にしていただきご自身のゲームに導入していただければと思います。

この記事がUnityでのゲーム開発のお役に立てば幸いです。