Hitbox và Hurtbox trong Unity3D
Phàm từ xưa đến nay, nhiều chuyện nghĩ thì đơn giản nhưng lúc bắt tay vào làm thì gặp rất nhiều vấn đề đau đầu. Ví dụ khi một nhân vật trong game thực hiện một đòn đánh nếu trúng đối phương thì đối phương sẽ nhận damage. Nhưng nếu bạn đang từng hoặc có ý định làm một con game hành động chặt chém, đối kháng chắc sẽ gặp những vấn đề ở phần này. Điển hình như:
- Làm thế nào để biết đòn đánh đó có trúng hay không?
- Làm thế nào để biết những đối phương nào trúng đòn đánh đó?
- Làm thế nào để kiểm soát khi nào đón đánh đó gây damage vào người đối phương?..
Tổng Quát
Để giải quyết triệt để những vấn đề trên, chúng ta cần nắm được những khái niệm cơ bản về hitbox, hurt box và Layer Collision Matrix trong Unity.
Vậy hitbox và hurtbox là gì? Chúng khác gì nhau?
Hitbox là một hình hộp (hoặc hình cầu) ẩn, dùng để xác định phạm vi đòn đánh.
Hurtbox cũng tương tự như hitbox, nhưng được gắn trên các object dùng để xác định object đó có bị trúng bởi đòn đánh hay không.
Để cho các bạn dễ hình dung trực quan hơn thì hãy tham khảo video dưới đây:
Trong Unity
Khái niệm thì chỉ có như thế thôi, vậy trong Unity chúng ta sẽ làm gì để tạo được Hitbox và Hurtbox. Unity có cung cấp cho chúng ta một API gọi là PhysicOverlap, nếu bạn muốn hiểu kĩ hơn về API này có thể tham khảo tại đây.
Setup Layer, Object tag và Box Collider
Điều đầu tiên cần lưu ý khi các bạn sử dụng đến vật lý và va chạm trong Unity đó là layer. Khi bạn muốn phân loại các object nào va chạm với nhau và object nào không, thì đó là lúc sử dụng Layer Matrix.
Đầu tiên mình sẽ tạo 2 object tương ứng với Player và Enemy. Hai object này đều mang layer là hurtbox. Tag của object Player là “Player”, còn của object Enemy là “Enemy”.
Tiếp theo là vào Edit -> Project Settings -> Physics 2D (Ở đây mình hướng dẫn trường hợp game 2D). Và setup như sau:
Trong trường hợp này, mình không muốn bất kỳ layer nào tương tác với layer “Hurtbox” nên mình sẽ bỏ hết tick đi.
Các bạn cần lưu ý là nếu project của các bạn sử dụng đến vật lý và va chạm của các collider thì nên bỏ tick hết các layer tương tác mặc định chỉ giữ lại layer nào bạn muốn chúng tương tác với nhau.
Vậy là xong phần Layer và Tag, tiếp theo chúng ta sẽ add BoxCollider2D vào 2 object vừa tạo. Kích thước của collider chính là kích thước của các unit trong game hay chính xác hơn là khoảng có thể đánh trúng trên mỗi unit.
Cuối cùng là tạo hitbox, thực chất khi một đòn đánh được thực hiện chúng ta sẽ gọi API Physic Overlap để vẽ ra một “cái hộp”. Để vẽ được một hitbox sẽ cần đến vị trí, kích thước, góc quay và layer tương tác. Những thông số đó đều có thể lấy từ Collider, vậy để trực quan hơn khi xử lý hitbox, chúng ta sẽ tạo child object cho cả player và enemy rồi gán Collider vào đó sau đó ẩn nó đi.
Lưu ý: Khi bạn điều chỉnh kích thước của Box Collider hãy luôn chắc răng Offset của nó là (0,0) .
Scripts
Cuối cùng là scripts, tuy là phần cốt lõi nhưng để code hitbox thì cũng không quá khó khăn vì API của Unity đã hỗ trợ gần hết.
Chúng ta sẽ tạo một class MonoBehaviour là Unit như sau:
public class BaseUnit : MonoBehaviour
{
public BoxCollider2D hitbox;
public LayerMask layerHurtbox;
public string tagEnemy;
public void TakeDamage(float damage)
{
Debug.Log("unit take " + damage + "damage");
}
private void ActiveHitbox()
{
BoxCollider2D[] hurtboxes = new BoxCollider2D[20];
int hurtboxesCount = Physics2D.OverlapBoxNonAlloc(hitbox.transform.position, hitbox.size, hitbox.transform.eulerAngles.z, hurtboxes, layerHurtbox);
if (hurtboxesCount > 0)
{
for (int i = 0; i < hurtboxesCount; i++)
{
if (hurtboxes[i].transform.root.CompareTag(tagEnemy))
{
BaseUnit unit = hurtboxes[i].GetComponent<BaseUnit>();
unit.TakeDamage(5f);
}
}
}
}
}