Tôi đã xây dựng Coroutine cho Game Engine của mình, rồi sau đó lại không dùng chúng

Tôi đã xây dựng một hệ thống generator coroutine cho game engine của mình. Nó chỉ có 122 dòng code và 12 bài kiểm tra (tests). Nó giải quyết được vấn đề callback hell. Nó khiến các script trông như những dòng code chạy thẳng.

Sau đó, tôi quyết định không dùng nó cho logic game. Thay vào đó, tôi sử dụng Finite State Machine (FSM).

Đây là lý do.

Hầu hết các hướng dẫn đều bỏ qua hai vấn đề cực kỳ lớn đối với generator trong các trò chơi thời gian thực: bộ nhớ và việc lưu trữ (saving).

1. Áp lực bộ nhớ (Memory Pressure)

Mỗi khi bạn gọi .next() trên một generator, engine JavaScript sẽ tạo ra một đối tượng mới. Đối tượng này chứa giá trị hiện tại và trạng thái.

Trong một vòng lặp game chạy ở mức 60 FPS, điều này tạo ra áp lực dọn rác (garbage collection) liên tục. Engine của tôi tuân thủ quy tắc zero-allocation để giữ hiệu suất ổn định. Generator phá vỡ quy tắc đó. Chúng tạo ra một luồng các đối tượng nhỏ trong mỗi khung hình.

2. Vấn đề về Serialization

Một trò chơi cần phải lưu và tải. Bạn cần chuyển đổi trạng thái hiện tại của game thành dữ liệu và ngược lại.

Bạn không thể serialize một generator đang tạm dừng. Trạng thái của nó nằm trong các slot nội bộ của engine mà bạn không thể truy cập được. Nếu bạn cố gắng lưu nó, bạn sẽ nhận được một đối tượng rỗng hoặc một lỗi.

Finite State Machine thì khác. Trạng thái chỉ đơn giản là một chuỗi (string) trên một component.

  • Để lưu: Ghi chuỗi đó vào đĩa.
  • Để tải: Đọc chuỗi đó và yêu cầu FSM bắt đầu từ đó.

FSM đã chiến thắng vì nó xử lý được hai thứ quan trọng nhất đối với một trò chơi chuyên nghiệp: hiệu suất và tính bền vững (persistence).

Cách lựa chọn:

Logic có nằm trong vòng lặp khung hình chính (main frame loop) không?

  • Không: Hãy dùng generator coroutine. Chúng rất tuyệt cho các luồng chạy một lần như tải tài nguyên (assets) hoặc hướng dẫn người chơi mới (onboarding).
  • Có: Hãy đặt câu hỏi tiếp theo.

Trạng thái có cần được duy trì sau khi lưu game không?

  • Có: Hãy dùng Finite State Machine.
  • Không: Hãy đặt câu hỏi tiếp theo.

Bạn có đang chạy nhiều chuỗi (sequences) cùng một lúc không?

  • Có: Hãy dùng Finite State Machine.
  • Không: Hãy dùng generator coroutine.

Generator không phải là một sai lầm. Chúng chỉ là công cụ không phù hợp cho "hot path". Hãy dùng chúng để kết nối các tác vụ bất đồng bộ (async glue), nhưng hãy dùng FSM cho logic game của bạn.

Source: https://dev.to/grzott/i-built-generator-coroutines-for-my-game-engine-then-didnt-use-them-o3g