Đứng trên mặt đất
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 11 trên 71.
Mỗi điểm tiếp xúc có một pháp tuyến: hướng có độ dài 1, vuông góc với bề mặt bạn chạm vào và hướng ra khỏi bề mặt đó, về phía đối tượng của bạn. collision.GetContact(0) là điểm tiếp xúc đầu tiên, còn normal cho bạn biết bạn đã chạm vào phía nào. Khi đứng trên mặt đất phẳng, pháp tuyến là (0, 1, 0); khi chạm vào bức tường bên phải, đó là (-1, 0, 0); khi đập đầu vào trần nhà, đó là (0, -1, 0).
Đoạn code này phân biệt giữa tiếp đất và va vào mặt bên:
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);
}
}Điều kiện kiểm tra là normal.y > 0.5f, chứ không phải bằng chính xác 1, để các mặt dốc cũng được tính là mặt đất: y bằng 0.5 trên mặt dốc 60 độ, dốc hơn mức mọi người có thể đi lên. Có thêm hai thông báo giúp xử lý mọi thứ kéo dài: OnCollisionStay chạy ở mỗi bước vật lý trong suốt thời gian tiếp xúc, còn OnCollisionExit chạy một lần khi tiếp xúc kết thúc. Khi tiếp xúc kết thúc, sẽ không có điểm tiếp xúc nào vì các đối tượng không còn chạm vào nhau, nên đừng gọi GetContact tại đó.
Thử thách
DễChỉ cho nhân vật nhảy khi đang đứng trên một vật gì đó.
- Thêm
private bool grounded;. TrongOnCollisionStay, đặt biến này thành true khicollision.GetContact(0).normal.y > 0.5f; trongOnCollisionExit, đặt thành false. - Trong
FixedUpdate(), chỉ nhảy khiif (jumpPressed && grounded), rồi đặtjumpPressed = false;sauifđó để bỏ qua lần nhấn khi đang ở trên không.
Nhấn Chơi và thử nhảy hai lần liên tiếp: lần nhấn thứ hai không có tác dụng. Sau đó nhấn Kiểm tra.
Tự làm thử
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;
}
}
}
Tất cả bài học trong Vật lý và lối chơi
1Rigidbody
Trọng lực và khối lượngĐẩy bằng AddForceNhảy bằng xung lựcFixedUpdate cho vật lýVận tốcVật thể động họcÔn tập: Bệ phóng4Coroutine
InvokeInvokeRepeating, CancelInvokeCoroutine đầu tiên của bạnVòng lặp trong CoroutineDừng CoroutineÔn tập: đếm ngược10Dự án: Thoát khỏi đấu trường
Đấu trườngThợ săn2Va chạm
OnCollisionEnterMình đã va chạm với gì?Vỡ khi va chạmĐứng trên mặt đấtĐộ nảy và ma sátHình dạng colliderÔn tập: Tường có thể phá vỡ5Dự án: Cuộc đua thu thập xu
Quả bóng lănThu thập xuTự luyện tập: Playground Unity