Như mọi khi, kiến trúc phụ thuộc vào yêu cầu của bạn. Bạn sẽ có bao nhiêu mob? AI của họ phức tạp đến mức nào? Nó phản ứng với cái gì? Làm thế nào thường xuyên nó thay đổi trạng thái của nó? Trả lời những câu hỏi này và bạn sẽ hiểu rõ hơn về những gì bạn muốn và làm thế nào để có được điều đó.
Nói chung, bạn muốn có ít nhất một số loại hệ thống sự kiện. AI thường được định nghĩa theo các sự kiện: "Khi A xảy ra, làm B"; và nếu bạn không có các sự kiện trong mã thực tế, bạn phải bằng cách nào đó dịch các định nghĩa này.
Theo kinh nghiệm của tôi, bạn có thể thoát khỏi việc thực hiện vòng lặp đơn giản khi bạn có một vài mob thực sự đơn giản (trái với những gì câu trả lời khác dường như gợi ý). Ví dụ, trong trò chơi hiện tại của chúng tôi, chúng tôi có hàng trăm trường hợp nhỏ với mỗi lần có tối đa 10 mob. Và những mob này là ngu ngốc; AI của 99% trong số họ có thể được mô tả trong một câu: "Tôi có tấn công ai không? Nếu không, hãy tấn công người chơi gần nhất". Trong trường hợp này, một vòng lặp đơn giản là quá đủ - hai lần một giây chúng tôi kiểm tra mục tiêu mới (và một vài thứ khác cho mob "thông minh" hiếm gặp), và điều đó thực hiện được.
Tuy nhiên, khi bạn có nhiều mob và / hoặc mob thông minh hơn, cách tiếp cận ngây thơ sẽ ngừng hoạt động. Để AI phản ứng với một số kích thích, bạn phải viết mã phát hiện nó bên trong vòng lặp AI của bạn. Ví dụ: giả sử mob của bạn nên làm gì đó "khi bị người chơi đánh". Với cách tiếp cận vòng lặp, không có cách nào dễ dàng để xác định mob bị tấn công. Khi AI đang chạy, bạn có thể kiểm tra xem sức khỏe của mob có bị giảm kể từ lần đánh dấu cuối cùng không, hoặc mob hiện đang được ai đó nhắm đến. Nhưng bạn không thể phát hiện các lượt truy cập thực tế mà không cần dùng đến hack, như lưu từng thông tin lần truy cập ở đâu đó để AI truy cập sau.
Thứ hai, một vòng lặp ngây thơ luôn luôn chạy, bất kể điều gì xảy ra. Khi bạn có nhiều mob, bạn muốn AI chạy nhanh nhất có thể .. và mã nhanh nhất là mã không bao giờ chạy cả. Nếu bạn có mob không hoạt động, bạn muốn chúng không chạy AI hoặc chỉ chạy nó một cách rời rạc (như trong, mob di động AI chỉ nên chạy khi nó quyết định đi đâu tiếp theo).
Với cách tiếp cận dựa trên sự kiện, bạn có thể yêu cầu các hệ thống con khác gửi các sự kiện AI bất cứ khi nào thuận tiện, loại bỏ vấn đề "phát hiện lượt truy cập". Tất nhiên, một số sự kiện vẫn sẽ yêu cầu phát hiện mã: ví dụ nổi tiếng nhất là sự kiện "tiếp cận". Và khi bạn không chạy thói quen AI của mình trong một vòng lặp khi không có gì xảy ra, bạn sẽ đạt được hiệu suất.
Bạn cũng có thể sử dụng một phương pháp lai. Thay vì xử lý các sự kiện AI ngay lập tức, bạn có thể nhét chúng vào một số loại hàng đợi. Sau đó, khi thói quen AI chạy (trong một vòng lặp), nó sẽ loại bỏ các sự kiện khỏi hàng đợi này và xử lý từng cái một. Với kiến trúc này, hiệu suất AI có thể chậm hơn một chút, nhưng nó dễ dự đoán hơn; đồng thời, bạn có thể đảm bảo rằng tất cả AI chạy trên một luồng duy nhất (điều này có thể khó khăn nếu không). Loại vòng lặp này cũng có thể dễ dàng được điều chỉnh bằng cách bỏ qua một số sự kiện (ví dụ: mỗi lần lặp AI chỉ xử lý ba sự kiện gần đây nhất, loại bỏ phần còn lại). Hoặc các sự kiện có thể được ưu tiên và những sự kiện ít quan trọng hơn sẽ bị loại bỏ nếu phát hiện ra AI bị tụt lại.
Nhìn chung, phương pháp "vòng lặp với hàng đợi sự kiện" có lẽ là linh hoạt nhất. Nhưng tôi muốn nhắc lại: đừng chỉ chọn nó một cách mù quáng là "tốt nhất". Trước tiên hãy nghĩ về yêu cầu của bạn và một số cách tiếp cận đơn giản hơn có thể trở nên tốt hơn.