Làm thế nào để các tác nhân AI truy cập thông tin về môi trường của họ?


9

Đây có thể là một câu hỏi tầm thường, nhưng tôi gặp khó khăn trong việc hiểu điều này. Rất đánh giá cao sự giúp đỡ của bạn.

Trong phát triển trò chơi bằng cách sử dụng thiết kế hướng đối tượng, tôi muốn hiểu làm thế nào các tác nhân AI truy cập thông tin họ cần từ thế giới trò chơi để thực hiện hành động của họ.

Như chúng ta đã biết, trong các trò chơi, các nhân viên AI rất cần phải 'nhận thức môi trường của họ' và hành động theo những gì đang xảy ra xung quanh họ. Ví dụ, một đặc vụ có thể được lập trình để đuổi theo người chơi nếu anh ta / cô ta đủ gần, tránh chướng ngại vật trong khi di chuyển (sử dụng hành vi điều khiển Tránh chướng ngại vật), v.v.

Vấn đề của tôi là tôi không chắc làm thế nào để làm điều đó. Làm thế nào một tác nhân AI có thể truy cập thông tin cần thiết về thế giới trò chơi?

Một cách tiếp cận có thể là các đặc vụ chỉ cần yêu cầu thông tin họ cần trực tiếp từ thế giới trò chơi.

Có một lớp gọi là GameWorld. Nó xử lý logic trò chơi quan trọng (vòng lặp trò chơi, phát hiện va chạm, v.v.) và cũng chứa các tham chiếu đến tất cả các thực thể trong trò chơi.

Tôi có thể biến lớp này thành Singleton. Khi một tác nhân cần thông tin từ thế giới trò chơi, họ chỉ cần lấy nó trực tiếp từ phiên bản GameWorld.

Ví dụ, một tác nhân có thể được lập trình cho Seekngười chơi khi anh ta / cô ta ở gần. Để làm được điều này, đặc vụ phải có được vị trí của người chơi. Vì vậy, nó chỉ có thể yêu cầu nó trực tiếp : GameWorld.instance().getPlayerPosition().

Một tác nhân cũng có thể lấy danh sách tất cả các thực thể trong trò chơi và phân tích nó theo nhu cầu của nó (để tìm ra những thực thể nào ở gần hoặc bất cứ thứ gì khác): GameWorld.instance().getEntityList()

Đây là cách tiếp cận đơn giản nhất: các đại lý liên hệ trực tiếp với lớp GameWorld và nhận thông tin họ cần. Tuy nhiên, đây là cách tiếp cận duy nhất tôi biết. Có cái nào tốt hơn không?

Làm thế nào một nhà phát triển trò chơi có kinh nghiệm sẽ thiết kế này? Là "có được một danh sách của tất cả các thực thể và tìm kiếm bất cứ điều gì bạn cần" ngây thơ? Có những cách tiếp cận và cơ chế nào để cho phép các tác nhân AI truy cập thông tin họ cần để thực hiện hành động của mình?


Nếu bạn có quyền truy cập vào đăng ký GDCVault, đã có một cuộc nói chuyện tuyệt vời vào năm 2013 có tên là "Tạo ra AI cho cuộc sống, thế giới thở của Hitman absolution" đi sâu vào mô hình kiến ​​thức AI của họ.
DMGregory

Câu trả lời:


5

Những gì bạn mô tả là một mô hình "kéo" cổ điển của việc truy vấn thế giới. Hầu hết thời gian, điều này hoạt động khá tốt, đặc biệt là đối với các trò chơi có AI cơ bản (hầu hết). Tuy nhiên, có một vài điểm bạn nên xem xét có thể là nhược điểm:

  • Bạn có thể muốn tăng gấp đôi bộ đệm. Xem các mẫu lập trình trò chơi về chủ đề này . Bằng cách luôn yêu cầu dữ liệu trực tiếp từ thế giới, bạn có thể nhận được các điều kiện chủng tộc kỳ lạ trong đó kết quả phụ thuộc vào thứ tự AI được gọi. Điều này có quan trọng với trò chơi của bạn hay không là để bạn xác định. Một kết quả có thể xảy ra là nó thiên vị trò chơi với bất kỳ ai đi "đầu tiên" hoặc "cuối cùng", khiến nhiều người chơi không công bằng.

  • Nó thường có thể hiệu quả hơn nhiều đối với các yêu cầu hàng loạt, đặc biệt là đối với các cấu trúc dữ liệu nhất định. Tại đây, bạn có thể làm cho mọi tác nhân AI muốn tìm kiếm chướng ngại vật tạo ra một "đối tượng truy vấn" và đăng ký nó với một đơn vị chướng ngại vật trung tâm. Sau đó, trước vòng lặp AI chính, tất cả các truy vấn được chạy ngược lại với cấu trúc dữ liệu, điều này giữ cho cấu trúc dữ liệu trở ngại nhiều hơn trong bộ đệm. Sau đó, trong phần AI, mỗi tác nhân xử lý kết quả truy vấn của nó, nhưng không được phép thực hiện trực tiếp nữa. Ở cuối khung, các đối tượng AI cập nhật các truy vấn với vị trí mới của chúng hoặc thêm hoặc xóa chúng. Điều này tương tự như thiết kế định hướng dữ liệu .

    Lưu ý rằng điều này về cơ bản thực hiện đệm đôi bằng cách lưu trữ kết quả của các truy vấn trong bộ đệm. Nó cũng yêu cầu bạn dự đoán xem bạn có cần thực hiện truy vấn khung trước đó hay không. Đây là mô hình "đẩy", bởi vì các tác nhân khai báo loại cập nhật nào họ quan tâm (bằng cách tạo một đối tượng truy vấn tương ứng) và các cập nhật này được đẩy tới chúng. Lưu ý bạn cũng có thể có đối tượng truy vấn chứa một cuộc gọi lại, thay vì lưu trữ tất cả các kết quả cho một khung.

  • Cuối cùng, bạn có thể muốn sử dụng các giao diện hoặc các thành phần cho các đối tượng có thể tìm kiếm của bạn hơn là kế thừa, được ghi lại ở nơi khác. Lặp lại một danh sách Entitieskiểm tra instanceOfcó lẽ là một công thức cho mã khá dễ vỡ, phút mà bạn muốn cả hai StaticObjectMovingObjectđược Healable. (trừ khi instanceOfhoạt động cho các giao diện trong ngôn ngữ bạn chọn.)


5

AI là tốn kém, hiệu suất thường là yếu tố thúc đẩy trong kiến ​​trúc.

Để giảm bớt những lo lắng của bạn xung quanh các mô hình truy cập dữ liệu, chúng ta hãy xem xét một vài ví dụ AI khác nhau cả trong và ngoài ngành công nghiệp trò chơi, hoạt động từ thứ xa nhất từ ​​điều hướng của con người đến thứ quen thuộc nhất với chúng ta.

(Mỗi ví dụ giả định một bản cập nhật logic toàn cầu duy nhất.)

  • A * con đường ngắn nhấtMỗi AI tính toán trạng thái của bản đồ cho các mục đích tìm đường. A * yêu cầu mỗi AI đã biết toàn bộ môi trường (cục bộ) mà nó phải tìm đường dẫn, vì vậy chúng ta phải cung cấp thông tin về chướng ngại vật và không gian bản đồ (thường là mảng boolean 2D). A * là một dạng chuyên biệt của Thuật toán Dijkstra, một thuật toán tìm kiếm đồ thị mở đường dẫn ngắn nhất; các cách tiếp cận như vậy trả về danh sách đại diện cho đường dẫn và trên mỗi bước, AI chỉ cần chọn nút tiếp theo trong danh sách này để bước tới, cho đến khi đạt được mục tiêu hoặc tính toán lại (ví dụ do thay đổi chướng ngại vật trên bản đồ). Không có kiến ​​thức này, không có con đường ngắn nhất thực tế có thể được tìm thấy. A * là lý do tại sao AI trong các trò chơi RTS luôn biết cách đi từ điểm A đến điểm B - nếu một đường dẫn tồn tại. Nó sẽ tính toán lại con đường ngắn nhất cho mỗi AI riêng lẻ, bởi vì tính hợp lệ của đường dẫn dựa trên vị trí của những AI đã di chuyển (và có khả năng bị chặn một số đường dẫn nhất định) trước đó. Quá trình lặp mà theo đó A * tính toán các giá trị ô trong quá trình tìm đường là một trong những phép hội tụ toán học. Người ta có thể nói kết quả cuối cùng giống như khứu giác trộn lẫn với cảm giác thị giác, nhưng trong tất cả, nó có phần xa lạ với suy nghĩ của chúng ta.

  • Khuếch tán hợp tác Cũng được tìm thấy trong các trò chơi, điều này gần giống nhất với khứu giác, dựa trên sự khuếch tán của các chất khí và hạt. CD giải quyết vấn đề xử lý lại tốn kém được tìm thấy trong A *: Thay vào đó, một trạng thái bản đồ duy nhất được lưu trữ, xử lý một lần trên mỗi bản cập nhật cho tất cả các AI và lần lượt kết quả được truy cập bởi mỗi AI để di chuyển tương ứng . Không còn là một đường dẫn duy nhất (danh sách các ô) được trả về bởi thuật toán tìm kiếm; thay vào đó, mỗi AI sẽ kiểm tra bản đồ sau khi nó được xử lý và di chuyển đến bất kỳ ô liền kề nào có giá trị cao nhất. Điều này được gọi là leo đồi . Tuy nhiên, giai đoạn xử lý bản đồ phải đãcó quyền truy cập trước vào thông tin bản đồ, ở đây cũng chứa vị trí của tất cả các cơ quan AI. Do đó, bản đồ tham chiếu AI, và sau đó AI tham chiếu bản đồ.

  • Tầm nhìn máy tính và phát sóng + con đường ngắn nhất Trong robot rover & drone, điều này đang trở thành tiêu chuẩn để xác định phạm vi không gian mà robot điều hướng. Điều này cho phép robot xây dựng một mô hình thể tích đầy đủ về môi trường của chúng, giống như chúng ta nhìn bằng mắt hoặc thậm chí âm thanh hoặc chạm (đối với người mù hoặc điếc), sau đó robot có thể giảm xuống thành biểu đồ địa hình tối thiểu (hơi giống như biểu đồ điểm tham chiếu được sử dụng trong các trò chơi có A *), theo đó các thuật toán đường đi ngắn nhất có thể được áp dụng. Trong trường hợp này, mặc dù "tầm nhìn" có thể cung cấp manh mối cho môi trường trực tiếp, nhưng nó vẫn dẫn đếnmột tìm kiếm đồ thị cuối cùng cung cấp đường dẫn đến mục tiêu. Điều này gần với suy nghĩ của con người: Để đến được nhà bếp từ phòng ngủ, tôi phải đi qua phòng khách. Thực tế là tôi đã nhìn thấy chúng và biết không gian và cổng thông tin của chúng, là những gì cho phép di chuyển được tính toán này. Đây là một cấu trúc liên kết đồ thị, áp dụng thuật toán đường dẫn ngắn nhất, mặc dù được nhúng trong protein mềm chứ không phải silicon cứng.

Vì vậy, bạn có thể thấy rằng hai người đầu tiên phụ thuộc vào việc biết toàn bộ môi trường. Điều này, vì lý do chi phí đánh giá một môi trường từ đầu, là phổ biến trong các trò chơi. Rõ ràng, cuối cùng là mạnh mẽ nhất. Một robot được trang bị theo cách này (hoặc ví dụ, AI trò chơi đọc bộ đệm sâu từng khung hình) có thể điều hướng đủ trong mọi môi trường mà không cần biết trước về nó. Như bạn có thể đoán, đó cũng là cách tốn kém nhất trong ba cách tiếp cận ở trên và trong các trò chơi, chúng ta thường không đủ khả năng để làm điều này trên cơ sở mỗi AI. Tất nhiên, nó ít tốn kém hơn trong 2D so với 3D.

Điểm kiến ​​trúc

Rõ ràng là chúng ta không thể giả sử chỉ có một mẫu truy cập dữ liệu chính xác cho AI; sự lựa chọn phụ thuộc vào những gì bạn đang cố gắng đạt được. Truy cập GameWorldtrực tiếp vào lớp là hoàn toàn tiêu chuẩn: nó chỉ đơn giản cung cấp cho bạn thông tin thế giới. Về cơ bản, đó là mô hình dữ liệu của bạn và đó là mô hình dữ liệu dành cho. Singleton là tốt cho việc này.

"lấy danh sách tất cả các thực thể và tìm kiếm bất cứ thứ gì bạn cần"

Không có gì ngây thơ về điều đó, cả. Điều duy nhất có thể ngây thơ là thực hiện nhiều lần lặp lại danh sách hơn bạn cần. Trong phát hiện va chạm, chúng tôi tránh điều này bằng cách sử dụng ví dụ: quadtrees để giảm không gian tìm kiếm. Các cơ chế tương tự có thể áp dụng cho AI. Và nếu bạn có thể chia sẻ cùng một vòng lặp để làm nhiều việc, hãy làm như vậy, bởi vì các chi nhánh rất tốn kém.


Cảm ơn đã trả lời. Vì tôi là người mới bắt đầu chơi trò chơi, tôi nghĩ bây giờ tôi sẽ sử dụng cách tiếp cận "lấy danh sách từ thế giới trò chơi" đơn giản :) Một câu hỏi: trong câu hỏi của tôi, tôi đã mô tả GameWorldlớp là lớp có chứa các tham chiếu đến tất cả các thực thể trò chơi, và cũng chứa hầu hết logic 'động cơ' quan trọng: vòng lặp trò chơi chính, phát hiện va chạm, v.v ... Về cơ bản, đó là 'lớp chính' của trò chơi. Câu hỏi của tôi là: Cách tiếp cận này có phổ biến trong các trò chơi không? Có một 'lớp học chính'? Hay tôi nên tách nó thành các lớp nhỏ hơn và có một lớp làm đối tượng 'cơ sở dữ liệu thực thể' có thể thăm dò?
Manila Cohn

@Prog Bạn được chào đón. Một lần nữa, không có gì trong các cách tiếp cận AI ở trên (hoặc bất kỳ cách nào khác, đối với vấn đề đó) cho thấy rằng "lấy danh sách từ thế giới trò chơi" là bất kỳ cách nào, hình dạng hoặc hình thức không chính xác về mặt kiến ​​trúc. Các AI kiến trúc phải phù hợp với nhu cầu của AI; nhưng logic đó, như bạn đề xuất, nên được mô đun hóa, đóng gói (trong lớp riêng của nó) khỏi kiến trúc ứng dụng rộng hơn của bạn . Có, các hệ thống con phải luôn được đưa vào các mô-đun riêng biệt sau khi có câu hỏi như vậy. Nguyên tắc hướng dẫn của bạn nên là SRP .
Kỹ sư

2

Về cơ bản tôi có 2 cách truy vấn thông tin.

  1. khi AIState thay đổi vì bạn đã phát hiện xung đột hoặc bất kỳ bộ đệm nào, tham chiếu đến bất kỳ đối tượng nào đều quan trọng. Bằng cách đó bạn biết những gì bạn cần tham khảo. Khi có các hệ thống khác phải chạy các tìm kiếm lớn, mọi khung hình đều khuyên bạn nên sao lưu chúng để bạn không phải thực hiện nhiều tìm kiếm. Vì vậy, 'va chạm' được phát hiện với khu vực khiến kẻ thù 'cảnh giác' gửi cho anh ta một tin nhắn / sự kiện đăng ký anh ta với đối tượng đó nếu anh ta chưa và thay đổi trạng thái trò chơi thành trạng thái anh ta kinh doanh dựa trên việc ở trong trò chơi đó Bạn cần một sự kiện thuộc loại nào đó bảo bạn thực hiện thay đổi, tôi chỉ cần chuyển một tham chiếu vào bất kỳ cuộc gọi lại nào bạn sử dụng để cung cấp thông tin đó. Điều này là mở rộng hơn sau đó chỉ cần phải đối phó với người chơi. Có thể bạn muốn một kẻ thù theo đuổi kẻ thù khác hoặc một số đối tượng khác. Bằng cách này, bạn chỉ cần thay đổi bất kỳ thẻ nào bạn xác định nó bằng.

  2. Với thông tin đó, sau đó bạn sẽ thực hiện truy vấn hệ thống tìm đường sử dụng A * hoặc một số thuật toán khác để cung cấp cho bạn đường dẫn hoặc bạn có thể sử dụng nó với một số hành vi lái. Có thể là sự kết hợp của cả hai hoặc bất cứ điều gì. Về cơ bản với sự biến đổi của cả hai bạn sẽ có thể truy vấn hệ thống nút hoặc navmesh của bạn và nó sẽ cung cấp cho bạn một đường dẫn. Thế giới game của bạn có thể có nhiều thứ khác sau đó tìm đường. Tôi chỉ gửi truy vấn của bạn để tìm đường dẫn. Ngoài ra, việc sắp xếp những thứ này có lẽ là tốt nhất nếu bạn có nhiều truy vấn vì điều này có thể trở nên khá chuyên sâu và việc tạo khối sẽ giúp thực hiện.

    Transform* targetTransform = nullptr;
    EnemyAIState  AIState = EnemyAIState::Idle;
    void OnTriggerEnter(GameObject* go)
    {
       if(go->hasTag(TAG_PLAYER))
       {
       //Cache important information that will be needed during pursuit
       targetTransform = go->getComponent<Transform>();
       AIState = EnemyAIState::Pursue;
       }
    }
    
    void Update()
    {
       switch(AIState)
       {
          case EnemyAIState::Pursue:
           //Find position to move to
           Vector3 nextNode = PathSystem::Seek(
                              transform->position,targetTransform->position);
           /*Update the position towards the target by whatever speed the unit moves
             Depending on how robust your path system is you might want to raycast
             against obstacles it can't take into account or might clip the path.*/
            transform->Move((nextNode - transform->position).unitVector()*speed*Time::deltaTime());
            break;
        }
     }
    
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.