Unityでキャラクターが動く床に乗ると一緒に動く仕組みガイド
この資料では、キャラクターが移動する床(Moving Platform)に乗った際、床の動きに連動してプレイヤーを移動させる3つのアプローチを紹介します。さらに、プレイヤーの移動がTransformによる座標更新(直接的な移動)またはRigidbodyを用いた物理演算ベースの移動の場合でも対応可能な点、そして特に方法1において床上で独自に移動するための注意点について解説します。
1. 床の作成方法
2D版の場合
- 作成手順:
GameObject > 2D Object > Sprite
を選択し、床用のスプライトを設定します。 - コンポーネント設定:
- Rigidbody2D: 追加し、
Body Type
をKinematic
に設定。 - Collider2D: 例として
Box Collider2D
を追加して当たり判定を設定。
- Rigidbody2D: 追加し、
3D版の場合
- 作成手順:
GameObject > 3D Object > Cube
を選択し、Cubeを床オブジェクトとして使用します。 - コンポーネント設定:
- Collider: Cubeには自動的に
Box Collider
が付与されます。 - Rigidbody: 追加後、「Is Kinematic」にチェックを入れ、物理演算の影響を抑制します。
- Collider: Cubeには自動的に
2. 各連動方法
方法1:キャラクターを床の子オブジェクトにする
概要
キャラクターが床に接触した際、床の子オブジェクトとして登録することで、床の移動に合わせて自動的に位置が連動します。
実装例
【2D版】
using UnityEngine;
public class CharacterOnPlatform : MonoBehaviour
{
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
transform.SetParent(collision.transform); // 床の子オブジェクトに設定
}
}
void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
transform.SetParent(null); // 親子関係を解除
}
}
}
【3D版】
using UnityEngine;
public class CharacterOnPlatform : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
transform.SetParent(collision.transform); // 床の子オブジェクトに設定
}
}
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
transform.SetParent(null); // 親子関係を解除
}
}
}
床上でのプレイヤー独自移動への対応(方法1の場合)
親子付けによりキャラクターは床のローカル座標系に入ります。
この状態でプレイヤー入力に基づく移動を行う際は、以下の点に注意してください。
- ローカル座標系での入力処理の調整
- 床の回転やスケールの影響を受けるため、入力ベクトルを床のローカル空間に合わせて変換する必要があります。
- 例として、
transform.Translate()
の第二引数にSpace.Self
を指定する方法があります。
- 床の回転・スケールの影響の補正
- プラットフォームが回転やスケール変更する場合、キャラクターの移動方向が予期せぬ方向に変わることがあるため、必要に応じて入力処理内で補正を行います。
【プレイヤー移動スクリプト例】
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 5f;
void Update()
{
// 左右の入力を取得
float horizontal = Input.GetAxis("Horizontal");
// ローカル座標系で移動(床の子になっている場合、親である床の座標系に合わせた移動となる)
Vector3 movement = new Vector3(horizontal * speed * Time.deltaTime, 0, 0);
transform.Translate(movement, Space.Self);
}
}
このスクリプトでは、キャラクターが床の子オブジェクトの場合でも、床上での独自移動が正しく反映されるようにローカル座標系での移動を行っています。
メリット・デメリット
- メリット:
実装がシンプルで、床の移動と連動した動作が安定して得られる。 - デメリット:
床の子オブジェクトになっているため、床の回転やスケールがキャラクターに影響する場合がある。そのため、床上での入力移動ではローカル座標系での調整が必要。
方法2:床の移動量をキャラクターに加算する
概要
床の移動量の差分を計算し、その分だけキャラクターの位置を直接更新する方法です。
キャラクターのTransform(回転やスケール)には影響を与えずに床の動きを反映できます。
実装例
【2D版】
using UnityEngine;
public class CharacterOnMovingPlatform : MonoBehaviour
{
private Transform platformTransform;
private Vector3 lastPlatformPosition;
private bool onPlatform = false;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
platformTransform = collision.transform;
lastPlatformPosition = platformTransform.position;
onPlatform = true;
}
}
void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
onPlatform = false;
}
}
void Update()
{
if (onPlatform)
{
Vector3 platformMovement = platformTransform.position - lastPlatformPosition;
transform.position += platformMovement;
lastPlatformPosition = platformTransform.position;
}
}
}
【3D版】
using UnityEngine;
public class CharacterOnMovingPlatform : MonoBehaviour
{
private Transform platformTransform;
private Vector3 lastPlatformPosition;
private bool onPlatform = false;
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
platformTransform = collision.transform;
lastPlatformPosition = platformTransform.position;
onPlatform = true;
}
}
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
onPlatform = false;
}
}
void Update()
{
if (onPlatform)
{
Vector3 platformMovement = platformTransform.position - lastPlatformPosition;
transform.position += platformMovement;
lastPlatformPosition = platformTransform.position;
}
}
}
メリット・デメリット
- メリット:
キャラクターのTransform(回転・スケール)には影響せず、床の移動量だけを反映できる。 - デメリット:
床の動きが急激な場合、キャラクターの移動が滑らかでなくなる可能性があります。
方法3:FixedJoint(FixedJoint2D)を使った物理的接続
概要
FixedJoint系のジョイントコンポーネントを利用して、キャラクターと床を物理的に結合する方法です。
物理演算に基づいた自然な連動動作が得られます。
実装例
【2D版 (FixedJoint2D)】
using UnityEngine;
public class AttachToPlatformWithJoint : MonoBehaviour
{
private FixedJoint2D fixedJoint;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
fixedJoint = gameObject.AddComponent<FixedJoint2D>();
fixedJoint.connectedBody = collision.rigidbody;
}
}
void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
Destroy(fixedJoint);
}
}
}
【3D版】
using UnityEngine;
public class AttachToPlatformWithJoint : MonoBehaviour
{
private FixedJoint fixedJoint;
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
fixedJoint = gameObject.AddComponent<FixedJoint>();
fixedJoint.connectedBody = collision.rigidbody;
}
}
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("MovingPlatform"))
{
Destroy(fixedJoint);
}
}
}
メリット・デメリット
- メリット:
物理演算により自然な連動動作が実現可能です。 - デメリット:
物理計算負荷が増すため、パフォーマンス面で注意が必要な場合があります。また、物理ベースの挙動を十分に調整する必要があります。
3. 適用可能な移動方式について
- Transformによる座標操作(直接的な位置変更)
→ 方法1(親子付け)および方法2(移動量加算)は、Transform操作によるプレイヤー移動に適用可能です。 - 物理演算ベースの移動(Rigidbodyを使用した移動)
→ 方法1、方法2も使用可能ですが、物理エンジンとの整合性(衝突判定、力の影響など)に注意が必要です。
→ より自然な物理連動を実現するには、方法3(FixedJoint/FixedJoint2D)の利用が推奨されます。
4. まとめ
Unityにおけるキャラクターと動く床の連動動作は、以下の3つの方法で実現できます。
- 方法1:キャラクターを床の子オブジェクトにする
- メリット: シンプルな実装で、床の移動と自動的に連動。
- デメリット: 床の回転やスケールの影響を受けるため、床上でのプレイヤー移動ではローカル座標系への対応が必要。
- 方法2:床の移動量をキャラクターに加算する
- メリット: キャラクターのTransform(回転・スケール)に影響せず、床の移動を反映可能。
- デメリット: 急激な床の動きには滑らかさが損なわれる可能性がある。
- 方法3:FixedJoint/FixedJoint2Dを使用して物理的に接続する
- メリット: 自然な物理挙動に基づく連動が実現できる。
- デメリット: 物理計算負荷やパフォーマンスへの影響に注意が必要。
また、これらの方法は、プレイヤーの移動がTransform操作による単純な座標更新の場合でも、Rigidbodyを用いた物理演算ベースの場合でも対応可能です。特に方法1の場合、床上でのプレイヤー移動を実現するためには、入力処理をローカル座標系に合わせて調整するなどの工夫が必要となります。プロジェクトの仕様やパフォーマンス要件に合わせ、最適な手法を選択して実装してください。
ディスカッション
コメント一覧
まだ、コメントがありません