Menu
CoddyTech

Kiểm tra mặt đất bằng tia

Thuộc phần Vật lý và lối chơi trong hành trình Unity của Coddy. Bài học 37 trên 71.

Cú nhảy chỉ nên bắt đầu khi nhân vật đứng trên mặt đất. Bài học Đứng trên mặt đất đã xác định điều đó dựa trên các pháp tuyến tiếp xúc, được cập nhật qua các thông báo va chạm. Tia truy vấn trả lời ngay tại chỗ, vào bất kỳ thời điểm nào, câu hỏi “mình có đang đứng trên vật gì không?”: chiếu tia thẳng xuống từ tâm, dài hơn một chút so với khoảng cách từ tâm đến đáy. Nhân vật này là một viên nang cao 2 đơn vị, nên đáy nằm thấp hơn tâm 1 đơn vị và tia dài 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);
}

Khoảng dư 0.1 tạo ra biên độ an toàn. Vật thể nằm trên sàn có thể ở cao hơn sàn một chút hoặc lún vào sàn một chút, vì vậy tia dài đúng 1 đôi khi không chạm được sàn trong một số khung hình. Tia dài hơn nhiều cũng không đúng: nếu dài 3, nhân vật có thể nhảy lần nữa khi đang ở trên không 2 đơn vị; còn nếu tia không có độ dài, nó luôn tìm thấy sàn, nên mỗi lần nhấn đều khiến nhân vật nhảy.

Tia bắt đầu bên trong bộ va chạm của chính nhân vật, nơi các tia bị bỏ qua, nên nó không bao giờ phát hiện nhân vật. Ta đọc phím trong Update(), vì GetKeyDown chỉ đúng trong một khung hình, và có thể thêm một xung lực tức thời ngay tại đó, như trong bài Nhảy bằng xung lực.

challenge icon

Thử thách

Trung bình

Chỉ cho ếch nhảy khi đang ở trên mặt đất.

  1. Thêm bool IsGrounded() để trả về Physics.Raycast(transform.position, Vector3.down, 0.85f): bán kính của ếch là 0.75, cộng thêm 0.1.
  2. Trong Update(), thêm && IsGrounded() vào câu lệnh if khi nhấn Space.

Nhấn Chơi rồi nhấn Space hai lần: ếch chỉ nhảy một lần. Sau đó nhấn Kiểm tra.

Tự làm thử

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);
        }
    }
}

Tất cả bài học trong Vật lý và lối chơi

Tự luyện tập: Playground Unity