Hitbox và Hurtbox trong Unity3D

24 Tháng Sáu, 2024

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”.

Player
Player
Enemy
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:

Setup cho Game 2D
Setup cho Game 2D

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.

Hurtbox
Hurtbox

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.

Hitbox object của Player
Hitbox object của Player
Object chưa thông tin hitbox
Object chưa thông tin hitbox

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

    }
0 0 đánh giá
Đánh giá bài viết
Theo dõi
Thông báo của
guest
0 Góp ý
Phản hồi nội tuyến
Xem tất cả bình luận
Tin tức liên quan
Các hàm cơ bản của Monobehaviour Unity: Update, LateUpdate, FixedUpdate
Với nhiều bạn mới làm quen với Unity, thì việc khi nào dùng Update, LateUpdate, FixedUpdate thường là khá mơ hồ. Thêm vào đó, ba hàm này ảnh hưởng...
Tương tác với Object đa nền tảng trong Unity
Với phần lớn game trên smartphone, việc tương tác với object trong game đa phần là dùng ngón tay. Vấn đề đặt ra ở đây là việc phát triển...
C# Extension trong Unity: Delay Action Coroutine
Việc chờ một khoảng thời gian rồi gọi một (hoặc nhiều) hàm trong một project thì cách đơn giản nhất là sử dụng Coroutine. Cách thông thường nhất là...
0
Rất thích suy nghĩ của bạn, hãy bình luận.x