レイを使った接地判定
CoddyのUnityジャーニー「物理演算とゲームプレイ」セクションの一部。レッスン 37/71。
ジャンプは地面にいるときだけ開始できるようにします。地面に立っているかどうかは、衝突メッセージによって最新の状態に保たれる接触法線から判定していました。レイを使えば、「何かの上に立っているか」をその場でいつでも確認できます。中心から真下に、中心から底面までの距離より少し長いレイを飛ばします。このプレイヤーは高さ2単位のカプセルなので、底面は中心から1単位下にあり、レイの長さは1.1です。
public float jumpForce = 5f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && IsGrounded())
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, 1.1f);
}追加した0.1は余裕分です。床の上で静止している物体は、床からほんの少し浮いたり、ほんの少し沈み込んだりすることがあるため、長さがちょうど1のレイでは、フレームによって検出できないことがあります。逆に長すぎてもいけません。長さを3にすると、プレイヤーは空中で2単位上昇したところでもう一度ジャンプできてしまいます。また、長さがまったくないとレイは常に床を検出するため、キーを押すたびにジャンプします。
レイはプレイヤー自身のコライダーの内側から開始しますが、レイは自身のコライダーを無視するため、プレイヤーを検出することはありません。GetKeyDownは1フレームだけtrueになるため、キー入力はUpdate()で読み取ります。また、「インパルスを使ったジャンプ」の例のように、その場で1回限りのインパルスを加えられます。
チャレンジ
中級カエルが地面からのみジャンプするようにします。
bool IsGrounded()を追加し、Physics.Raycast(transform.position, Vector3.down, 0.85f)を返します。これはカエルの半径0.75に0.1を加えた値です。Update()で、Spaceキーのifに&& IsGrounded()を追加します。
「プレイ」を押してSpaceキーを2回押します。カエルは1回だけジャンプします。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
public class Hopper : MonoBehaviour
{
public float jumpForce = 6f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
}
物理演算とゲームプレイのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド