はじめに
今回は2Dのジャンプアクションを作る際に、少し実装が大変な移動床の実装方法を紹介します。
サンプル
動作サンプルはこちらとなります。
左右キーで移動で、Spaceキーでジャンプします。
プロジェクトファイルもダウンロードできます。こちらのソースコードは自由に使ってもらってOKです。
移動床オブジェクトの設定
移動床には通常のコリジョンとは別に、プレイヤーが上に乗っているかどうかのトリガーコリジョンをかぶせます。
トリガーコリジョンが左右に少しはみ出しているのは、左右の壁に当たったときに跳ね返る動きをするためです。もし跳ね返りをしないのであれば、左右のはみ出しは不要となります。
それと Rigidbody2D
で物理挙動をシミュレートしたいのであれば、Gravity Scale
は「0」、Is Kinematic
にチェックを入れます。
それとFixed Angle
も念のためチェックを入れています。
プレイヤーの設定
トリガーコリジョンに接触しているのがプレイヤーかどうかを判定するために、プレイヤーをLayerグループに登録します。
このようにLayersに「Player」グループが作成済みであるとします(Groundグループは壁や床の判定に使っています)。
PlayerのLayerを「Player」に登録します。
移動床のスクリプト
移動床のスクリプトは以下のように記述します。(必要な部分のみを抜粋しています)
/// 移動床
public class FloorMove : Token
{
// 前回の更新時のX座標
float _xprevious = 0;
// プレイヤーの参照
Player _target = null;
/// トリガーイベント発生
void OnTriggerEnter2D (Collider2D other)
{
string name = LayerMask.LayerToName (other.gameObject.layer);
if (name == "Player") {
// プレイヤーに当たったので参照を保持
_target = other.gameObject.GetComponent<Player> ();
}
}
/// トリガーイベント終わり
void OnTriggerExit2D (Collider2D other)
{
string name = LayerMask.LayerToName (other.gameObject.layer);
if (name == "Player") {
// プレイヤーがいなくなったので参照を消す
_target = null;
}
}
/// 更新
void Update ()
{
// 前回の座標からの差分を求める
float dx = X - _xprevious;
if (_target != null) {
// 上にプレイヤーが乗っていたら動かす
_target.X += dx;
}
// 現在の座標を次に使うように保存
_xprevious = X;
}
}
まずメンバ変数に、前回のフレームの座標(_xprevious
)とプレイヤーの参照(player
)を用意します。そしてOnTriggerEnter2Dイベントでトリガーコリジョンへの衝突を検知します。ここでは衝突したのがPlayer
であるかどうかを判定して、プレイヤーであれば、その参照を変数_player
に保持しています。そしてOnTriggerExit2Dイベントで、トリガーコリジョンからプレイヤーが離れたら参照を消すようにしています。
最後のUpdate関数で、前回からの移動量を計算し、Playerの参照があれば直接座標を足しこんで、移動床と同じ速度で移動させています。ちなみに大文字の「X」は transform.position.x
を独自にラッパーしたプロパティとなります。
注意点
プレイヤーが移動床に乗った状態でDestroy(死亡など)するとnull参照エラーとなります。
そのため、「プレイヤーが移動床に乗ったまま消滅する」可能性があるときは何らかの対策が必要となります。