Unityで「プレイヤー(キャラクター)が地面に着地しているかを判定する」を実装していきます。いわゆる接地判定というものですね。
色々な方法がありますが、今回はRaycastを利用していきます。Raycastは接地だけでなく、オブジェクト(物)の有無判定にも使えます。
はじめに
Unityのバージョンは「2021.3.14f1」で作成しています。
2Dゲームで「プレイヤー(キャラクター)が地面に着地している時だけジャンプできる」を実装していきます。2段ジャンプをできないようにするという感じですね。Raycastを利用します。
実装開始
「UI作成」→「プレイヤーの動作作成(Script)」→「接地判定の追加(Raycast)」の順番で行います。
フィールドとプレイヤーのオブジェクト作成
「2DObject」→「Sprites」→「Square」を2つ追加。名前を「Player」と「Ground」とします。
PlayerオブジェクトにはAddComponentから「BoxCollider2D」と「Rigidbody2D」の2つをアタッチ。
GroundはBoxCollider2Dをアタッチ、位置、スケール、色を変更しておきます。
下記の様な感じにします。白い四角がプレイヤー、黒い下部分が地面です。
プレイヤーのジャンプを実装
PlayerJumpと言う名前で、下記のスクリプトを作成。
using UnityEngine; public class PlayerJump : MonoBehaviour { [SerializeField] private float jumpPower = 5.0f; private Rigidbody2D _rb; void Start() { _rb = GetComponent<Rigidbody2D>(); } void Update() { if (Input.GetKey(KeyCode.Space)) _rb.velocity = new Vector2(0, jumpPower); } }
スペースキーを押したらジャンプするという簡単なものです。
プレイヤーにアタッチして実行してみます。下記のように、スペースキーを押してジャンプすればOK、連続でスペースを押すと2段ジャンプ、3段ジャンプをします。
接地判定の追加
「プレイヤーが地面に着地している時だけ」ジャンプできるようにスクリプトを下記の様に変更します。
using UnityEngine; public class PlayerJump : MonoBehaviour { [SerializeField] private float jumpPower = 5.0f; [SerializeField] private LayerMask groundLayer; private Rigidbody2D _rb; void Start() { _rb = GetComponent<Rigidbody2D>(); } void Update() { if (Input.GetKey(KeyCode.Space) && isGrounded()) _rigidbody.velocity = new Vector2(_rigidbody.velocity.x, jumpPower); } private bool isGrounded() { RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.6f, groundLayer); return hit.collider != null; } }
Raycastを直訳すると「Ray=光線」、「cast=投げる」と言う感じですかね。センサーを出して、接触したオブジェクトを検知するという感じです。
上記のRaycastのパラメータは、「センサーの発射位置」、「方向」、「長さ」、「対象のレイヤー」です。
プレイヤーオブジェクトの位置から下方向に短いセンサーを飛ばし、当たったか当たっていないかを判定しているという感じです。
GroundのLayerに「Ground」を追加。
スクリプトのパラメータをセットします。
プレイヤーが地面に着地している時しかジャンプ出来なければOK。(2段ジャンプの禁止)
ギズモ
実際にセンサーがどう出ているのかをGizmoで表示してみます。
スクリプトに下記を追加。
void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawRay(transform.position, new Vector3(0, -0.6f, 0)); }
シーン画面に赤線が出ます。この赤線にGroundオブジェクトが触れると検知されます。
今回は地面に触れているのかを判定するので下方向に飛ばしていますが、上に飛ばしたり、横に飛ばすことで他にも利用できますね。