Hành Trình Đầu Tiên Với Trình Soạn Thảo StarCraft II - nói dối e blog

Hành Trình Đầu Tiên Với Trình Soạn Thảo StarCraft II

Gần đây, tôi được giao nhiệm vụ cải tiến hệ thống AI quái vật trong dự án game hiện tại. Nhóm thiết kế mong muốn trực tiếp cấu hình logic hành vi thay vì phải viết tài liệu yêu cầu để nhờ lập trình viên triển khai.

Phiên bản trước gặp vấn đề nghiêm trọng về hiệu năng - ngay cả khi chạy thử nghiệm không có người chơi, chỉ cần dựng vài tình huống đơn giản đã khiến CPU chạy ở mức cao đáng ngạc nhiên. Tôi nhận ra nguyên nhân nằm ở hai điểm: thứ nhất, hệ thống cho phép tùy biến quá chi tiết; thứ hai, kiến trúc底层 được xây dựng không phù hợp, dẫn đến hàng ngàn dòng mã Lua chạy vòng lặp vô ích.

Hệ thống AI hiện tại áp dụng mô hình “mỗi NPC có một script độc lập”, sử dụng cơ chế nhịp tim khoảng 0.5 giây để định kỳ đánh thức các thực thể kiểm tra hành vi. Mọi quyết định đều phải chạy qua các script được thiết kế trong sandbox. Khi đo đạc thực tế, mỗi nhịp tim có thể phải thực thi hàng chục nghìn dòng mã Lua - điều này giải thích vì sao hiệu năng tụt giảm nghiêm trọng.

Khác với lập trình ứng dụng thông thường, trong phát triển game, việc đạt được kết quả đúng không đồng nghĩa với hoàn thành nhiệm vụ. Yếu tố thời gian thực thi đóng vai trò then chốt: Nếu một tác vụ không hoàn thành trong khung thời gian cho phép, thì dù thuật toán có chính xác đến đâu cũng trở thành vô nghĩa. Những điểm nghẽn hiệu năng nhỏ lẻ không đáng để tối ưu nếu chỉ cần nâng cấp phần cứng là khắc phục được. Muốn cải thiện hiệu năng vượt cấp độ, phải thay đổi tận gốc rễ cách tiếp cận yêu cầu - từ “làm gì” đến “cách làm”.

Đó là lý do tôi quyết định tìm hiểu cách làm của trình soạn thảo StarCraft II.

Dù chưa từng sử dụng trình soạn thảo của Warcraft 3 hay StarCraft II, tôi biết rằng các công cụ này cho phép người dùng sáng tạo đa dạng thể loại game, không bị gò bó trong khuôn khổ RTS. Với hơn một thập kỷ phát triển, hệ thống bản đồ tùy chỉnh của Blizzard hẳn đã tích lũy được nhiều mô hình xử lý kinh điển.

Tiếc rằng tài liệu hướng dẫn chi tiết gần như không tồn tại. Trang chủ Blizzard chỉ cung cấp tài liệu cơ bản về ngôn ngữ Galaxy - thứ ngôn ngữ kịch bản tích hợp sẵn trong trình soạn thảo. Mọi thao tác GUI đều có thể chuyển thành đoạn mã Galaxy tương ứng, nhưng tài liệu hướng dẫn sử dụng lại không được công bố rộng rãi. Có vẻ Blizzard khuyến khích người dùng tạo bản đồ thông qua giao diện trực quan, còn kịch bản chỉ là công cụ “phía hậu trường”.

Tôi đành tự mày mò trải nghiệm, cố gắng suy luận nguyên lý xử lý của Blizzard qua hai ngày nghiên cứu. Những nhận định dưới đây chắc chắn còn nhiều thiếu sót, rất mong nhận được góp ý từ các chuyên gia.

Quan điểm thiết kế khác biệt

Điểm khác biệt đầu tiên nằm ở góc nhìn: Người viết script trong StarCraft II không bị giới hạn trong từng thực thể đơn lẻ, mà tiếp cận thế giới game như vị thần toàn năng. Điều này hoàn toàn trái ngược với thiết kế trước đây của chúng tôi.

Hệ thống game tùy chỉnh được xây dựng từ hai thành phần chính:

  1. Dữ liệu: Bao gồm địa hình, vị trí đặt đơn vị, đường dẫn, điểm mốc, vùng không gian… Tất cả đều được tạo dễ dàng qua giao diện trực quan.
  2. Mã lệnh: Được tổ chức thành các Trigger (kích hoạt), mỗi Trigger mang tên duy nhất và tồn tại độc lập trong cấu trúc dữ liệu bản đồ.

Khi tải bản đồ, tất cả Trigger sẽ được nạp vào RAM. Về sau, mã chỉ có thể bật/tắt các Trigger đã được định nghĩa sẵn - không thể tạo Trigger mới trong quá trình chạy chương trình, điều này phản ánh rõ quan điểm thiết kế “tiên liệu trước” của Blizzard.

Cấu trúc Trigger

Mỗi Trigger gồm bốn thành phần:

  • Sự kiện (Event): Điều kiện khởi phát Trigger, có thể là “đơn vị chết”, “unit bị tấn công”, hoặc “người chơi nhấn nút giao diện”.
  • Điều kiện (Condition): Bộ lọc logic quyết định Trigger có thực sự được kích hoạt.
  • Hành động (Action): Chuỗi lệnh cần thực thi.
  • Biến cục bộ: Các biến số chỉ tồn tại trong phạm vi Trigger.

Blizzard đầu tư mạnh vào thiết kế hệ thống sự kiện. Mỗi sự kiện đều có tên ngắn dùng trong mã (ví dụ: UnitDies) và mô tả đầy đủ hiển thị trên giao diện (ví dụ: “Khi đơn vị quân sự chết”). Hệ thống hỗ trợ đa ngôn ngữ, kèm theo chú thích chi tiết giúp người dùng hiểu rõ chức năng.

Phân tách lệnh và hành động

Một trong những khám phá thú vị nhất là cách StarCraft II tách biệt Order (lệnh)Action (hành động):

  • Order: Là các lệnh tuần tự được xếp vào hàng đợi của đơn vị (ví dụ: di chuyển đến điểm A).
  • Action: Là các hành động tức thì (ví dụ: xóa đơn vị, dịch chuyển tức thời).

Khi cần thực hiện thao tác kéo dài như di chuyển theo đường dẫn, Trigger sẽ gửi lệnh Order vào hàng đợi. Có ba cách thêm Order:

  1. Xóa hàng đợi cũ và thay thế bằng lệnh mới.
  2. Thêm lệnh vào cuối hàng đợi.
  3. Chèn lệnh vào vị trí hiện tại (thực thi ngay nhưng không xóa lệnh cũ).

Cơ chế đợi (Wait)

Hệ thống Trigger đặc biệt hỗ trợ ba loại lệnh đợi:

  1. Chờ khoảng thời gian nhất định (ví dụ: hiển thị thông báo sau 10 giây).
  2. Chờ một Trigger khác kích hoạt.
  3. Chờ điều kiện logic được thỏa mãn.

Cơ chế này cho phép xây dựng các quy trình phức tạp, thậm chí đạt đến mức Turing-complete với các cấu trúc điều kiện và vòng lặp đầy đủ.

Ví dụ minh họa

Giả sử cần thực hiện chuỗi hành động: “Di chuyển đến điểm A → Dừng 5 giây → Di chuyển đến điểm B”. Trong StarCraft II, ta phải làm như sau:

  1. Tạo Trigger A: Khi đơn vị đến điểm A → Gửi lệnh di chuyển đến B.
  2. Tạo Trigger B: Khi Trigger A kích hoạt → Chờ 5 giây → Gửi lệnh di chuyển.

Khác với thiết kế của chúng tôi trước đây, việc phân biệt rõ ràng giữa Order (gắn với đơn vị) và Action (thuộc hệ thống tổng thể) giúp tối ưu hiệu năng đáng kể.

Bộ lọc sự kiện nâng cao

Mỗi sự kiện đều có cơ chế lọc tiền xử lý:

  • Lọc theo giá trị: Chọn sẵn đối tượng trong bản đồ.
  • Lọc theo biến: Gán biến toàn cục được cập nhật từ Trigger khác.
  • Lọc theo hàm số: Ví dụ: “gần điểm nhất” (closure gắn với điểm mốc).
  • Lọc tùy chỉnh: Viết mã kịch bản riêng.

Cơ chế này giúp hệ thống chỉ kích hoạt Trigger khi sự kiện thực sự liên quan, tránh lãng phí tài nguyên xử lý những tình huống không cần thiết.

Bài học rút ra

Trải nghiệm tìm hiểu trình soạn thảo StarCraft II mang lại nhiều cảm hứng:

  1. Phân tầng logic rõ ràng: Tách biệt dữ liệu và
0%