Gaming Fundamentals: Làm Quen Với Event-based

Gaming Fundamentals: Làm Quen Với Event-based

Event-based là phương pháp giải quyết vấn đề dựa trên sự kiện được kích hoạt (Trigger) và kéo theo đó các hành động (Action) liên quan sẽ được thực hiện. Event gần như là yếu tố bắt buộc trong việc thiết kế User Interface (UI) nhờ vào hiệu năng và khả năng Custom của mình.

Khi nói đến Event-based trong game, 1 ví dụ có thể dùng để tham khảo là Blizzard nếu các bạn chưa biết thì Blizzard thường xuyên cho phép game thủ tạo ra Custom map cho tựa game của họ (Warcraft III, Starcraft II) bằng cách cung cấp tool cho phép tạo custom map là World Editor và Map Editor tương ứng với Warcraft và Starcraft. Dựa vào những Event đã được cung cấp sẵn thông qua những tính năng cơ bản của game, người làm map hoàn toàn có thể tạo ra 1 tựa game của riêng mình cũng chính là cách mà những custom map nổi tiếng như DotA, DDay Judgement, Thiên kiếm,... ra đời.

Tổng quan

Phương pháp Event-Based giống như đồng hồ báo thức, được định nghĩa sẵn để thông báo cho 1 tình huống đang hoặc đã diễn ra những hành động tiếp theo sẽ phụ thuộc vào tình huống được thông báo. Vì vậy khả năng giải quyết vấn đề của Event-Based rất đa dạng, không bị ràng buộc vào 1 vấn đề cụ thể nào cả.

Trước khi bắt đầu, để biểu thị 1 Action trong Event cụ thể chúng ta sẽ sử dụng cấu trúc như sau:

  • Event: "Tên sự kiện"
  • Condition: "Điều kiện đi kèm"
  • Action: "Hành động được kéo theo"

Một Event có thể có nhiều Actions, mỗi Action sẽ đi kèm với Condition. Bởi vì mỗi khi 1 Event được Trigger, tất cả các Action đều sẽ được kéo theo, tuy nhiên không phải Action nào cũng cần được thực hiện vì vậy chúng ta cần Condition để kiểm tra Action nào phù hợp.

Hãy thử 1 ví dụ: Mặc định rằng chúng ta đã có Event "A Unit Died" được trigger mỗi khi có 1 Unit trong game chết đi, và chúng ta muốn thực hiện tính năng cộng tiền khi giết được kẻ thù ta sẽ có

  • Event: "A Unit Died"
  • Condition: "Killed Unit is Enemy of Killing Unit" (Cả 2 là đối thủ của nhau)
  • Action: "Add n gold to Killing Unit"

Hãy cùng tìm hiểu các ưu điểm và nhược điểm mà Event-Based mang lại

Extensibility - Khả năng mở rộng

Event-Based cực kì tiềm năng trong mảng Custom vì vậy không có gì lạ khi Extensibility (khả năng mở rộng) là ưu điểm đầu tiên được đề cập đến. Tính năng trong DotA cực kì đa dạng và tất nhiên không thể bỏ qua khả năng mở rộng của Event mang lại cho tựa game này.

Trong mô hình Event lý tưởng, Event sẽ là điểm bắt đầu và các Action sẽ là điểm kết thúc, nghĩa là phía sau Action sẽ không còn hành động nào khác điều đó đảm bảo rằng việc thay đổi Action sẽ không ảnh hưởng đến bất kì Logic khác do đó giữa Event và Action sẽ không tồn tại bất kì ràng buộc nào. Đến lúc này, việc thay đổi tính năng chỉ còn gói gọn lại trong việc lựa chọn 1 Event phù hợp để thêm Action và tất nhiên Action là tính được thêm vào nên sẽ không ảnh hưởng đến những tính năng đã tồn tại.

Hãy thử làm 1 ví dụ về Ability "Bad Juju" của Dazzle khi có Aghanim Scepter trong DotA 2, theo phần mô tả "Dazzle sẽ tấn công các mục tiêu xung quanh mỗi khi sử dụng Ability". Thay vì phải thêm code vào cho Ability Bad Juju và kiểm tra nếu Aghanim Scepter đang tồn tại trong rương đồ hãy thử dùng Event. Phần mô tả đã chỉ rõ Event cần sử dụng là "A Unit cast an Ability", mỗi khi Aghanim được trang bị ta sẽ thêm Action vào cho "A Unit cast an Ability", chúng ta sẽ giả định "A Unit cast an Ability" được trigger mỗi khi có 1 Unit bất kì sử dụng Ability và chúng ta sẽ có

  • Event: "A Unit cast an Ability"
  • Condition: "CastingUnit learned Bad Juju and CastingUnit owning Aghanim Scepter"
  • Actions: "Pick 8 Units in range of CastingUnit and create an attack from Casting Unit to Picked Unit"

Dazzle khi đã có Aghanim's Scepter

Tuy nhiên việc Test và Debug lại gặp trở ngại lớn khi mà để test được tính năng, ta cần phải xác định được trường hợp gây lội và mô phỏng lại toàn bộ quy trình kích hoạt Event vì các tham số liên quan đến Event không cố định nên hoàn toàn có thể xuất hiện ngoại lệ, nghĩa là vấn đề không đến từ Action mà đến từ các tham số liên quan đến Event.

Lấy ví dụ ở trên, khi xuất hiện lỗi "Killing Unit" không nhận được tiền, ta cần phải xác định được "Killing Unit" là ai và mô phỏng lại quá trình "Killing Unit" giết được kẻ thù sau đó mới tim đến lí do.

Performance

Dựa vào cách mà Event và Action tương tác với nhau ta có thể thấy ưu điểm performance của Event-based đến từ 2 yếu tố cơ bản:

  • Tăng khả năng thực hiện phép toán.
  • Giảm số lượng phép toán cần thực hiện.

Từ việc Action và Event hoàn toàn độc lập với nhau do đó Action hoàn toàn có thể chạy bất đồng bộ, một yếu tố không thể thiếu khi nhắc đến high performance.

Action được thực hiện đúng thời điểm, khi so sánh với những cách làm như Wait hay Loop để kiểm tra điều kiện thực hiện Action, Event-based cải thiện được các vấn đề thời điểm thực hiện của Wait và số bước cần thực hiện của Loop, từ đó giảm số lượng phép toán cần thực hiện.

Nhưng vấn đề là yếu tố "Giảm số lượng phép toán" của Event-based bị phụ thuộc vào Event mà Event thì được định nghĩa bởi lập trình viên vậy nên việc Performance mang lại hiệu quả cao hay thấp bị phụ thuộc vào lập trình viên và vấn đề cần được giải quyết.

Vẫn là ví dụ về Bad Juju ở trên, điều kiện để Event được Trigger là "CastingAbility equal to Bad Juju", theo như định nghĩa mỗi lần có 1 Unit bất kì cast ability, Event "A Unit cast an ability" đều sẽ được Trigger. Do độ phức tạp khi 1 Event được Trigger là O(n) với n là số lượng Action nên nếu số lượng Ability được cast (ngoại trừ Bad Juju) có thể cast ability nằm ở mức nhỏ (< 10) vấn đề có lẽ không quá lớn nhưng rõ ràng là càng nhiều Unit cast ability thì performance sẽ càng tệ vì Event-Based không thể phân biệt được Action nào cần được thực hiện và Action nào sẽ bị bỏ qua. Hướng giải quyết cho vấn đề này là giảm phạm vi ảnh hưởng của Event để giảm lượng Action không cần thiết được gọi.

Sử dụng Event hiệu quả

Để sử dụng Event 1 cách hiệu quả, ta cần phải làm rõ khi nào thì Event sẽ mang đến hiệu quả tiêu cực, từ những ưu và nhược điểm đã được đề cập ở trên ta thể chỉ ra 1 số điểm chung cần lưu ý khi dùng event

  • Event và Action hoàn toàn độc lập với nhau, đó cũng là cơ sở để Action có thể chạy bất đồng bộ nhưng cũng vì vậy Action không thể trả về giá trị vì Event là người gọi Action và Event không quan tâm Action sẽ làm những gì.
  • Khi 1 Event được trigger, những thông tin liên quan đến Event nên được cung cấp đầy đủ.
  • Một Event nên giải quyết được càng nhiều vấn đề càng tốt, nếu Event chỉ dùng để giải quyết 1 vấn đề duy nhất, khả năng custom của Event sẽ bị lãng phí.
  • Không nên tồn tại 1 Event có thể thay thế hoàn toàn 1 Event khác nếu không có 1 mục đích đặc biệt nào khác.
  • Có thể dùng nhiều Event để giải quyết 1 vấn đề phức tạp, khi đó chúng ta sẽ có nhiều lựa chọn hơn để giải quyết vấn đề.

Lời kết

Event-based không phải là phương pháp hoàn hảo, nó là phương pháp trade-off (trao đổi) ưu điểm hay nhược điểm phụ thuộc vào cách dùng của lập trình viên và vấn đề cần giải quyết, ưu điểm lúc này cũng có thể là nhược điểm lúc khác. Vì vậy khi sử dụng Event ta hoàn toàn có thể tự do làm điều mình thích, miễn là nó phù hợp và mang lại hiệu quả!