【Unity】動く床の作り方

動く床の作り方 ゲーム制作メモ

UnityではTransformの値を変更することで、アクションゲームでよくある「動く床」をかなり簡単に作ることができます。しかし単純にその方法で動く床を作ると、プレイヤーキャラが床と一緒に移動せずに滑り落ちてしまう…という問題があります。

そこで今回は「乗るとプレイヤーも一緒に動く移動床」の作り方を紹介します。完成イメージは次のGIFのとおりです。

動く床の例(1) 動く床の例(2)

スポンサーリンク

今回作る「動く床」の仕組み

では、作り方を説明する前に今回作る「動く床」の仕組みについて簡単に説明します。

今回のような「乗るとプレイヤーも一緒に動く移動床」を作る方法は2通りほど考えられるのですが、ここでは「床に乗っている間だけ、プレイヤーを床の子オブジェクトにする」という仕組みを採用することにしました。

Unityでは子オブジェクトのTransformは親オブジェクトのTransformを基準にするので、プレイヤーを床の子オブジェクトにすることで、プレイヤーが床と一緒に移動するようになります。ゲームオブジェクトの親子関係はSetParentというメソッドで変更できるので、スクリプトではこのメソッドを使えばOKです。

あとは「床に乗っている間だけ」というのを実現するために、コライダーのOnTriggerEnter等を活用してスクリプトを組んでいきます。

動く床の作り方

それでは動く床の作り方を見ていきましょう。

トリガーの作成

動く床のトリガー

まず、動く床のゲームオブジェクトに上の画像のようなトリガーをアタッチします。このとき、トリガーを床の上面いっぱいにすると側面からぶつかったときもプレイヤーを検知してしまうため、少しだけ小さめに設定しておくのがポイントです。

動く床のC#スクリプト

あとは簡単なC#スクリプトを書くだけです。ここでは「BaseObstacleController」という障害物に共通する処理を持つ基底クラスを作り、それを継承して動く床のクラス「ReciprocatingObstacle」を作っています。

BaseObstacleController(障害物の基底クラス)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BaseObstacleController : MonoBehaviour
{

  [SerializeField]
  protected float waitTime = 0;

  protected bool stop = false;

    protected virtual void Start()
    {
        
    }

    protected virtual void Update()
    {
        
    }

  protected virtual void FixedUpdate()
  {

  }

  protected virtual IEnumerator WaitTimer()
  {
    stop = true;

    yield return new WaitForSeconds(waitTime);

    stop = false;
  }

}

ReciprocatingObstacle(動く床のクラス)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReciprocatingObstacle : BaseObstacleController
{

  [SerializeField]
  protected float moveX = 0;
  [SerializeField]
  protected float moveY = 0;
  [SerializeField]
  protected float moveZ = 0;
  [SerializeField]
  protected float speed = 0;

  protected float step;
  protected bool goBack = false;
  protected Vector3 origin;
  protected Vector3 destination;

  protected override void Start()
  {
    origin = transform.position;
    destination = new Vector3(origin.x - moveX, origin.y - moveY, origin.z - moveZ);
  }

  protected override void FixedUpdate()
  {
    if (stop)
    {
      return;
    }

    step = speed * Time.deltaTime;

    if (!goBack)
    {
      transform.position = Vector3.MoveTowards(transform.position, destination, step);

      if (transform.position == destination)
      {
        goBack = true;

        StartCoroutine(WaitTimer());
      }
    }
    else
    {
      transform.position = Vector3.MoveTowards(transform.position, origin, step);

      if (transform.position == origin)
      {
        goBack = false;

        StartCoroutine(WaitTimer());
      }
    }
  }

  protected virtual void OnTriggerEnter(Collider other)
  {
    if (other.gameObject.CompareTag("Player"))
    {
      other.gameObject.transform.SetParent(gameObject.transform);
    }
  }

  protected virtual void OnTriggerExit(Collider other)
  {
    if (other.gameObject.CompareTag("Player"))
    {
      other.gameObject.transform.SetParent(null);
    }
  }

}

パラメータについて

  • moveX,Y,Z:移動量
  • speed:速さ
  • waitTime:端まで移動したときに停止する時間

おわりに

以上、簡単ではありますが動く床の作り方をご紹介しました。これがあるとアクションゲーム等のステージ作りが楽しくなるので、今回の内容を参考にしてぜひ実際に作ってみてください。