Làm cách nào để đồng bộ hóa trạng thái trò chơi nhiều người chơi hiệu quả hơn so với cập nhật toàn trạng thái?


10

Tôi đã thực hiện một mã hóa mạng trò chơi nhỏ trước đây, nhưng chủ yếu là với TCP cho các trò chơi không có nhu cầu thời gian thực. Tôi đang làm việc trên một trò chơi Java 2D với nhiều người chơi được nối mạng. Để học, tôi muốn tự làm việc này mà không cần API mạng hiện có.

Làm cách nào để thể hiện hiệu quả trạng thái trò chơi được gửi cho khách hàng từ máy chủ? Có một cách rõ ràng nhất nhưng có lẽ là kém hiệu quả nhất, đó là tạo một số loại đối tượng bối cảnh trạng thái trò chơi với từng vị trí, trạng thái hoạt hình, v.v., và gửi nó cho mỗi người chơi mỗi bản cập nhật . Điều đó dường như không quá khó để thực hiện, nhưng có lẽ sẽ quá lớn để đạt được bất cứ điều gì gần với tương tác thời gian thực (tất nhiên kinh nghiệm của tôi với điều này bị hạn chế nên tôi có thể không chính xác).

Có một cách chắc chắn mà bất kỳ ai trong số các bạn đã sử dụng trước đây chỉ để truyền các thay đổi về trạng thái và thậm chí có sự chênh lệch đủ lớn trong hiệu suất mà nó đáng để làm thêm không?


2
Hãy thử trạng thái đầy đủ mọi khung hình và nếu nó quá chậm (đối với trò chơi 2d đơn giản, có lẽ nó đủ hiệu quả), sau đó thử tối ưu hóa. Nếu nó hoạt động tốt, thì nó hoạt động tốt và bạn không phải thay đổi nó trừ khi bạn nhận thấy mạng của bạn là một nút cổ chai sau này.
Robert Rouhani

Câu trả lời:


10

Truyền tải những trạng thái trò chơi đầy đủ thường xuyên là thường không khả thi, mặc dù nó phụ thuộc rất nhiều vào sự phức tạp của bạn trò chơi. Đối với một trò chơi đơn giản với một mô hình thế giới nhỏ, nó có thể hoạt động.

Cá nhân tôi đã thành công hơn nhiều với mô hình sau:

  • Trạng thái trò chơi được lưu trữ trong mô hình đối tượng được xác định rõ trong cấu trúc dữ liệu không gian (ví dụ: octree)
  • Tất cả các thay đổi về trạng thái trò chơi (cho dù trên máy khách hoặc máy chủ) được mô tả là sự kiện. Một sự kiện có thể là thay đổi thuộc tính trên một đối tượng trò chơi, thay đổi đối với ô bản đồ, chuyển động của đối tượng trò chơi, v.v.
  • Công cụ trò chơi trên máy chủ tạo ra một luồng các sự kiện khi trò chơi tiếp tục. Chúng được áp dụng trực tiếp vào trạng thái trò chơi của máy chủ.
  • Các sự kiện cũng được gửi cho người chơi, nhưng chỉ khi sự kiện đó có liên quan đến người chơi đó (ví dụ: sự kiện có thể nhìn thấy từ vị trí hiện tại không?)
  • Thay đổi về khả năng hiển thị của người chơi cũng có thể dẫn đến các sự kiện "tiết lộ" các phần mới của bản đồ, v.v. khi người chơi di chuyển. Điều này cũng có thể được sử dụng để đảm bảo rằng người chơi có được cái nhìn ban đầu chính xác về trạng thái trò chơi có liên quan khi họ lần đầu tiên tham gia trò chơi.
  • Trạng thái trò chơi cho người chơi được cập nhật với bất kỳ sự kiện nào họ nhận được. Do đó, nó chỉ có một phần mô hình trạng thái trò chơi, nhưng nó phải đồng bộ với máy chủ giả sử tất cả các sự kiện được xử lý chính xác

Điều này đã cung cấp hiệu suất tốt cho tôi với các thế giới trò chơi khá lớn.

Một mẹo khác, hãy để khách hàng chăm sóc hoạt hình, hiệu ứng hạt, v.v. mà không cần tham khảo máy chủ. Không có điểm nào truyền những thứ này - chúng chỉ cần được "kích hoạt" bởi các sự kiện trò chơi thích hợp.


6

Đồng bộ hóa thường được chia thành hai phần: gia tăng và tuyệt đối.

Đôi khi bạn phải truyền tải mọi thứ, nó rất lớn, nhưng nếu bạn đóng gói đúng cách bạn có thể làm điều này cứ sau vài giây. Nó là tốt để đặt everithing tại chỗ, sửa chữa các lỗi của làm mới gia tăng.

Để đạt được trải nghiệm thời gian thực, bạn phải truyền một số thay đổi nhanh chóng, nhưng chỉ các thuộc tính có thể thay đổi. Ví dụ: nếu một tên lửa bay theo đường thẳng, bạn không cần cập nhật vị trí, mỗi khách hàng có thể tính toán nó từ điểm bắt đầu. Nhưng khi nó bắn trúng, bạn có thể tạo một thông báo về nó, vì vậy mỗi khách hàng có thể phát nổ tên lửa ở đúng nơi. Trục trặc nhỏ có thể được bỏ qua.

Tất nhiên bạn chỉ cập nhật công cụ, khi họ có thể ảnh hưởng đến khách hàng! Một cái gì đó xa màn hình là không đáng. Một số giá trị có thể được cập nhật ít thường xuyên hơn. Ví dụ, các vị trí quan trọng là chính xác hơn hoặc ít hơn, các sự kiện (chết, bắn bị bắn, nổ, v.v.) phải được gửi ngay lập tức, trong khi các giá trị không quan trọng trực tiếp có thể có thời gian làm mới thấp hơn, ví dụ như bảng điểm, trò chuyện.

Việc đóng gói dữ liệu cũng rất quan trọng. Bạn có thể truyền khoảng 1400 byte (phụ thuộc vào cấu hình, đây là mặc định) trong một gói UDP, thường có một vài byte tiêu đề. Vì vậy, bạn có thể cập nhật 50-100 vị trí đơn vị trong một gói dễ dàng.


Cảm ơn lời khuyên Matzi. Tôi vẫn đang tiếp tục triển khai máy chủ và máy khách, nhưng tôi sẽ kiểm tra lại sau một vài ngày và có thể chấp nhận câu trả lời của bạn.
Haz

Chúc bạn may mắn! ;)
Matzi

1

Tùy thuộc vào trò chơi của bạn, bạn có thể xem xét mô hình "thực thi đồng bộ hóa" trong đó mỗi khách hàng chơi cùng một trò chơi bằng cách chia sẻ các đầu vào không xác định như đầu vào bàn phím / cần điều khiển và các sự kiện hẹn giờ. (So ​​với một mô hình nơi mỗi khách hàng chạy mô phỏng cục bộ và mong muốn tích hợp kết quả từ mô phỏng từ xa). Công cụ trò chơi của bạn thường cần phải được xác định đầy đủ để làm việc này, đây có thể là một gánh nặng lớn tùy thuộc vào trò chơi. Nhưng nếu trò chơi đã mang tính quyết định, đây có thể là một cách tiếp cận dễ dàng hơn.

Bài đăng #AltDevBlogADay này bao gồm một số khía cạnh của phương pháp này trong RTS hiện đại (cụ thể là cách phát hiện khi khách hàng của bạn bắt đầu chạy các trò chơi "khác nhau".)

Tuy nhiên, hãy nhớ giữ cho nó đơn giản cho đến khi được chứng minh. :)


1
Đây là những bài đọc hay từ nhà phát triển Factorio sử dụng phương pháp này và gợi ý về sự phức tạp của phương pháp này, nhưng cũng cho thấy nó khả thi: Factio.com/blog/post/fff-76 Factio.com/blog/post/fff -147 factorio.com/blog/post/fff-188
AaronLS
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.