Menu
CoddyTech

地面に立つ

CoddyのUnityジャーニー「物理演算とゲームプレイ」セクションの一部。レッスン 11/71。

すべての接触には法線があります。これは長さが1の方向ベクトルで、触れた面に垂直に、その面から離れてあなたのオブジェクトの方を向いています。collision.GetContact(0)は最初の接触点で、そのnormalがどちら側に触れたかを示します。平らな地面に立っているときは(0, 1, 0)、右側の壁に接しているときは(-1, 0, 0)、天井に頭をぶつけたときは(0, -1, 0)です。

このコードでは、着地と横からの衝突を判別します。

void OnCollisionEnter(Collision collision)
{
    Vector3 normal = collision.GetContact(0).normal;
    if (normal.y > 0.5f)
    {
        Debug.Log("Landed on " + collision.gameObject.name);
    }
    else
    {
        Debug.Log("Bumped the side of " + collision.gameObject.name);
    }
}

テストにnormal.y > 0.5fを使い、ちょうど1とはしないのは、傾斜も地面として扱うためです。60度の傾斜ではyが0.5になり、人が歩いて上れる傾斜より急です。さらに、続いている接触に関するメッセージを2つ追加できます。OnCollisionStayは接触が続いている間、物理演算のステップごとに実行され、OnCollisionExitは接触が終わったときに1回実行されます。接触が終わると何も触れていないため、接触点はありません。そのため、そこでGetContactを呼び出さないでください。

challenge icon

チャレンジ

簡単

プレイヤーが何かの上に立っている間だけジャンプできるようにします。

  1. private bool grounded;を追加します。OnCollisionStayでcollision.GetContact(0).normal.y > 0.5fのとき、これをtrueに設定します。OnCollisionExitではfalseに設定します。
  2. FixedUpdate()ではif (jumpPressed && grounded)の場合のみジャンプし、そのifの後にjumpPressed = false;を設定して、空中での入力を無効にします。

「プレイ」を押して二段ジャンプを試してみましょう。2回目の入力では何も起きません。その後、「確認」を押します。

自分で試してみよう

using UnityEngine;

public class Hopper : MonoBehaviour
{
    public float speed = 4f;
    public float jump = 6f;
    private Rigidbody rb;
    private bool jumpPressed;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            jumpPressed = true;
        }
    }

    void FixedUpdate()
    {
        float h = Input.GetAxisRaw("Horizontal");
        rb.linearVelocity = new Vector3(h * speed, rb.linearVelocity.y, 0);
        if (jumpPressed)
        {
            rb.AddForce(Vector3.up * jump, ForceMode.Impulse);
            jumpPressed = false;
        }
    }
}

物理演算とゲームプレイのすべてのレッスン

自分で練習してみよう: Unityプレイグラウンド