Hệ thống thành phần thực thể - tiến trình trò chơi


8

Tôi còn khá mới mẻ trong việc phát triển trò chơi (nhưng không phải lập trình) và tôi đang cố gắng tìm ra cách tốt nhất để xử lý giao tiếp giữa các thế giới. Ý tôi là thế này:

Tôi đã đọc về các hệ thống thành phần thực thể (ECS) và cách mọi người đề xuất sử dụng các thế giới / không gian khác nhau ( http://gamedevelopment.tutsplus.com/tutorials/spaces-usiously-game-object-containers--gamedev-14091 ) cho một phần phụ của một trò chơi. Ví dụ, một HUD, kho đồ hoặc chiến đấu / chuyển động, mỗi cái có một thế giới / không gian riêng biệt (vì chúng có đồ họa khác nhau và logic cơ bản.

Tuy nhiên, tôi đã tự hỏi làm thế nào hàng tồn kho, hoặc HUD biết về sức khỏe của người chơi khi sức khỏe được xử lý bởi một không gian / thế giới khác, ví dụ như khi chiến đấu?

Điều này cũng áp dụng cho tiến trình trò chơi nói chung, ví dụ như hộp thoại với NPC (hộp thoại sẽ là một không gian riêng vì nó là màn hình bật lên) nhưng bạn sẽ chuyển các lựa chọn trong (hoặc trạng thái) của hộp thoại sang các không gian / thế giới khác như thế nào . Hoặc về cơ bản là bất kỳ loại sự kiện nào khác ảnh hưởng đến tiến trình trò chơi trong các không gian / thế giới khác nhau (sức khỏe, mana, nhiệm vụ, hộp thoại, chiến đấu, kiểm kê, hud, v.v.)

Làm thế nào một người sẽ xử lý loại thiết kế này? Nó có cần một đối tượng singleton (đang thực hiện) chứa tất cả các loại thông tin này không? Điều đó thật kỳ lạ bởi vì sau đó, componentscần phải truyền tải từng thay đổi cho đối tượng đơn lẻ này, cảm giác như thực hiện hai lần (đi ngược lại DRY chính của lập trình) ...

Tôi thua lỗ ở đây về mặt thiết kế, có con trỏ nào không?


---BIÊN TẬP---

Vì vậy, tôi đã đọc một vài bài viết khác được đề xuất bởi các bình luận và có một ý tưởng chung về các khả năng, tuy nhiên mỗi bài trong số chúng dường như có một nhược điểm lớn khiến chúng không đúng. Rất có khả năng tôi đang giám sát các chi tiết sẽ giải quyết những nhược điểm này vì vậy hãy thoải mái sửa chữa cho tôi. Tôi sẽ cố gắng đưa ra một cái nhìn tổng quan cũng như một số câu trả lời cho một số câu hỏi.

Tôi đang thấy ba tùy chọn chính để 'chia sẻ' dữ liệu giữa các không gian. Mặc dù hầu hết các bài viết là về chia sẻ dữ liệu giữa các hệ thống, tôi cảm thấy như có thể được áp dụng tương tự để chia sẻ dữ liệu giữa các hệ thống.

1. Truy vấn

Ví dụ : Nếu thế giới HUD cần biết sức khỏe hiện tại của người chơi, nó có thể truy vấn một thế giới khác và yêu cầu sức khỏe hiện tại.

Nhược điểm : Các thế giới cần biết về nhau, đây là một vấn đề phụ thuộc lớn và đi ngược lại với việc tách rời.

2: Nhắn tin trực tiếp (đồng bộ hóa và không đồng bộ)

Ví dụ : Nếu trong khi chiến đấu, sức khỏe của người chơi thay đổi, nó có thể gửi tin nhắn (đồng bộ hóa và không đồng bộ, bất cứ điều gì cần thiết) đến các thế giới khác cần biết về thay đổi này.

Nhược điểm : Vẫn là vấn đề tách rời: thế giới cần biết về nhau.

3: Nhắn tin gián tiếp (đồng bộ hóa và không đồng bộ) <- tùy chọn tốt nhất

Ví dụ : Nếu trong khi chiến đấu, sức khỏe của người chơi thay đổi, nó có thể gửi tin nhắn (đồng bộ hóa và không đồng bộ, bất cứ điều gì cần thiết) đến trung tâm thông báo chung. Các thế giới / hệ thống khác cần biết về thay đổi này được đăng ký vào kênh tin nhắn cụ thể và đọc các tin nhắn.

Ưu điểm : Hoàn toàn tách rời, dễ quản lý và có thể mở rộng.

Nhược điểm / không rõ ràng : Khi nào kênh tin nhắn biết rằng các tin nhắn cần phải bị xóa? Hoặc có thể hệ thống được đăng ký nhãn hiệu (chỉ dành cho chính nó) tin nhắn như đã đọc và chờ tin nhắn mới -> hộp thư trở nên rất lớn sau một thời gian. Làm thế nào để thế giới / hệ thống xử lý trật tự? Ví dụ: trong khung: nếu HUD đã bỏ phiếu thông báo sức khỏe và sau đó sức khỏe thay đổi, khung tiếp theo HUD sẽ được cập nhật. Đối với một số ứng dụng, điều này có thể không đúng cách.

Q: Một đối tượng trò chơi có thể tồn tại trong nhiều không gian

Tôi đang sử dụng khung công tác ECS của Artemis đi kèm với các không gian tích hợp (được gọi là thế giới). Mỗi thực thể (và với nó, dữ liệu ở dạng các thành phần) được tạo trên một thế giới và do đó không thể chia sẻ giữa các thế giới.


Nhắn tin là cách tiếp cận tiêu chuẩn ở đây: gamedev.stackexchange.com/questions/23834/
Mark

Từ những gì tôi có thể đọc trong bài viết được liên kết, một đối tượng trò chơi có thể tồn tại dưới nhiều không gian. Nếu bạn có đồ họa hoặc logic khác nhau giữa các không gian, hãy tách dữ liệu khỏi đồ họa và logic. Chia sẻ đối tượng trò chơi dữ liệu trên các không gian và tổng hợp nó với các đối tượng trò chơi logic và đồ họa khác nhau.
Andreas

Câu trả lời này tôi đã đưa ra về các hệ thống nhắn tin cũng có thể giúp bạn hiểu rõ: gamedev.stackexchange.com/questions/7718/ ám
James

Tôi đã thực hiện cả ba giải pháp (truy vấn, trực tiếp và gián tiếp) trong cuộc sống gamedev của mình. Và tôi có thể nói rằng lựa chọn thứ ba phù hợp nhất với tôi. Bạn có thể dễ dàng tách rời các hệ thống và chạy logic của chúng song song. Nhược điểm duy nhất là bạn phải thực hiện 9 chức năng gọi để định tuyến mọi tin nhắn / sự kiện duy nhất từ ​​hệ thống này sang hệ thống khác. Rõ ràng bạn có thể tối ưu hóa nó và điểm cộng lớn là bạn không cần mutexes hoặc singletons trong phương pháp này.
Gregory

@Gregory Cảm ơn bạn đã tham gia, tôi mong muốn tin nhắn gián tiếp là lựa chọn tốt nhất. Tôi đã không nhận thức được 9 cuộc gọi chức năng nhưng khi lên kế hoạch cho tin nhắn này, tôi nhận ra rằng thực sự nó sẽ có khá nhiều cuộc gọi. Bạn đã bao giờ tìm thấy một giải pháp tốt / thay thế cho việc xóa tin nhắn khi không còn hệ thống nào cần chúng nữa?
Tim

Câu trả lời:


1

Một cách để xem xét đó là bạn có thể đặt quá nhiều vào các đối tượng trò chơi của mình.

Không có lý do gì mà mã thực sự nối HUD với nhu cầu trò chơi trong thế giới của bạn phải ở trong một thành phần / hệ thống sống trong một không gian cụ thể. Mã đó có lẽ sẽ tốt hơn khi sống trong một trình quản lý trung tâm hoặc tập lệnh toàn cầu có quyền truy cập vào tất cả các không gian và tất cả các đối tượng, sau đó có thể tương tác với mã biết khi nào thực sự tạo một khoảng trắng và những gì cần đặt vào chúng (ví dụ mã giúp sinh ra người chơi, lưu trạng thái giữa các cấp, v.v.).

Bạn cũng có thể có một "không gian chính" chứa các đối tượng trò chơi bằng logic hoặc dữ liệu cần duy trì quá khứ hoặc thao tác các không gian được sử dụng cho các cấp độ và giao diện người dùng. Cách tiếp cận này phổ biến trong các công cụ buộc các nhà phát triển đặt tất cả các tập lệnh / logic lên các thành phần / đối tượng (ví dụ: trong Unity, bạn sẽ tạo một đối tượng Chính toàn cầu và đặt nó ở trạng thái không tải trong cảnh; nếu Unity thực sự có khoảng trắng, bạn ' d sử dụng những cái đó thay vì cờ).

Hãy nhớ rằng, lạm dụng ECS ​​của bạn cũng giống như lạm dụng các mẫu thiết kế; chỉ vì bạn có một số công cụ mới tiện lợi không có nghĩa là bạn phải sử dụng nó để giải quyết mọi vấn đề bạn gặp phải. Đánh giá không gian vấn đề của bạn và chọn giải pháp phù hợp nhất, ngay cả khi đó là điều tồi tệ cũ mà tổ tiên của bạn đã sử dụng trong thời kỳ đen tối của những năm 90. : p


0

Tôi đã tạo một vài nguyên mẫu nhưng không có gì quá lớn và cách tôi sử dụng để xử lý nhiều không gian chỉ đơn giản là tạo một đối tượng trò chơi có chứa, thế giới, người chơi, v.v. và hơn là tôi thiết lập một số thuộc tính được yêu cầu bởi một số không gian khác, ví dụ như sức khỏe , trong đối tượng trò chơi

Bất cứ khi nào được gọi, nó sẽ có được sức khỏe của người chơi. bằng cách đó tôi có thể gửi nó đến HUD và hiển thị thanh sức khỏe.

Nó không phải là sạch nhất nhưng nó hoàn thành công việc, tôi đã thực hiện một số thử nghiệm hiệu suất vào năm 2013 và mọi thứ dường như hoạt động trơn tru. để tránh những phụ thuộc như vậy, bạn luôn có thể bỏ thanh sức khỏe khi sức khỏe của người chơi là null.

Thông thường khi người chơi không tồn tại, điều đó có nghĩa là người dùng đang ở trong menu hoặc cảnh cắt.

Mã ví dụ:

public float PlayerHealth {
  get {
    if (player !+ null) 
      return player.Health;
    return -1;
  }
}

Hy vọng đây là những gì bạn đang tìm kiếm.


0

đây là điều mà tôi thực sự đang làm việc trong vài tuần qua. Tôi đang làm việc trên thư viện ECS của riêng mình (muốn làm điều đó để có kinh nghiệm và chỉ để dùng thử, vì tôi đã muốn làm điều đó khá lâu).

Đây là liên kết github: https://github.com/gioragutt/xna-ecs

Đối với vấn đề của bạn, tôi đã luôn viết một thư viện pubsub nhỏ, bạn có thể thấy ở đây

Về cơ bản, tôi có một EmsClientlớp học, thứ có thể bắt nguồn từ đó. Hiện tại, các thành phần của tôi không làm điều đó, nhưng các lớp cấp cao hơn, mặc dù không có lý do gì để không. Tôi đăng ký Tên của tin nhắn và cung cấp một cuộc gọi lại với chữ ký sau : Action<JObject>. Như bạn đã hiểu, tôi đang sử dụng Json Object làm phương tiện để chuyển tin nhắn. Tôi đã làm điều này sau khi trước đây tôi chỉ sử dụng byte[]và tôi thấy rằng tôi cần một cái gì đó chung chung hơn và vì tôi đã quen với những thứ tương tự từ nơi làm việc của mình (chúng tôi có một IPCD hoạt động tương tự, ngoại trừ cuộc gọi lại phương pháp luôn giống nhau, vì thông thường chúng ta tách trách nhiệm với các trình xử lý khác nhau).

Có một EmsServer(một trên máy chủ và một trên mỗi máy khách) chịu trách nhiệm di chuyển các tin nhắn giữa EmsClienttrên vương quốc của nó ( EmsServerở phía máy chủ di chuyển các tin nhắn giữa EmsClientsphía máy chủ, ngược lại cho phía máy khách).

Đối với tin nhắn giữa Client và Server, tôi tạo ra một EmsServerEndpointmà là một EmsClientmình, ông chỉ không logic của bộ đệm các tin nhắn gửi đi trên đó của vương quốc, và xả nước họ cõi khác (FE client gửi thông điệp đến máy chủ, trong khi đó khi máy chủ chuyển từng tin nhắn đến tất cả các máy khách được kết nối.

Bạn có thể thấy việc sử dụng trong rất nhiều nơi, fe: ClientGameManager, ServerGameManager.

Trong khi đó, ví dụ của bạn, nếu tôi muốn thêm một thành phần GUI cho trình phát, bạn có thể xem TẠI ĐÂY , BeginAllocateLocalBeginAllocateRemotecác phương thức chịu trách nhiệm xây dựng trình phát GameObjects. Mỗi cái GameObjectchứa một Entity(từ lib ECS) và một IComponentContainer(cũng vậy, từ lib ECS). Mỗi người GameObjecttự động nhận được một biến đổi (như trong Unity, từ đó tôi lấy cảm hứng).

Mã của tôi nói lên nhiều điều về bản thân nó, và nếu bạn nhận được nó, tôi đang tìm kiếm những lời chỉ trích cho nó, vì vậy tôi muốn một số lời chỉ trích mang tính xây dựng :)

Hy vọng rằng mã của tôi sẽ giúp bạn với một số ý tưởng!


0

Xem xét các thành phần mẫu quan sát / chủ đề cho các thành phần trò chơi và các thành phần ui của bạn. Bạn cắm chúng lại với nhau khi tạo / tải lên và sau đó quên chúng đi. Nếu sức khỏe của nhân vật thay đổi, nó sẽ thông báo cho tất cả các nhà quan sát, họ có thể làm bất cứ điều gì họ muốn với thông tin.

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.