Chạy một mô phỏng vật lý trên cả máy khách và máy chủ?


13

Tôi đang triển khai một tiểu hành tinh nhiều người chơi để tìm hiểu về kiến ​​trúc mạng máy khách / máy chủ trong các trò chơi. Tôi đã dành thời gian đọc các ấn phẩm của GafferOnGames và Valve về công nghệ máy khách / máy chủ của họ. Tôi đang gặp rắc rối với hai khái niệm.

  1. Hiện tại tôi có một máy chủ trò chơi có thẩm quyền mô phỏng vật lý với box2d và gửi trạng thái của thế giới cho khách hàng khoảng 20 lần mỗi giây. Mỗi khách hàng theo dõi một vài ảnh chụp nhanh cuối cùng mà họ nhận được và lerps giữa hai trạng thái để làm dịu chuyển động của các họa tiết. Tuy nhiên nó không được suôn sẻ. Nó có thể trơn tru trong một thời gian, sau đó giật một chút, sau đó trở lại trơn tru, v.v. Tôi đã thử cả TCP và UDP, cả hai đều giống nhau. Bất cứ ý tưởng vấn đề của tôi có thể là gì? (Lưu ý: Tôi đã triển khai điều này cho người chơi đơn trước tiên và chuyển động sprite hoàn toàn mượt mà ở tốc độ 60fps khi cập nhật thế giới vật lý chỉ 20 lần mỗi giây).

  2. Để giải quyết vấn đề đầu tiên, tôi nghĩ có lẽ khách hàng cũng nên chạy mô phỏng box2d và chỉ cập nhật vị trí của các họa tiết của nó để khớp với ảnh chụp nhanh của máy chủ khi chúng không khớp. Tôi nghĩ rằng điều này có thể mượt mà hơn vì việc thực hiện một người chơi của tôi diễn ra suôn sẻ. Đây có phải là một ý tưởng tốt?

    Ngay cả khi nó không khắc phục được vấn đề trên, nó có cần thiết cho dự đoán phía khách hàng không? Ví dụ, nếu người chơi cố gắng di chuyển con tàu của họ, làm sao họ biết nếu họ đâm vào một tiểu hành tinh, tường hoặc tàu địch mà không có mô phỏng vật lý? Có vẻ như con tàu của họ sẽ xuất hiện xuyên qua vật thể mà nó sẽ va chạm trước khi họ nhận được một bức ảnh chụp từ máy chủ cho biết họ đã đâm vào vật thể.

Cảm ơn!

Câu trả lời:


10

Chắc chắn chạy mô phỏng trên cả máy khách và máy chủ. Bất cứ điều gì khác có độ trễ quá dài. Bạn nên chắc chắn rằng các mô phỏng khớp với nhau bằng cách chèn các đối tượng theo cùng một thứ tự, sử dụng bước thời gian cố định và tránh so sánh con trỏ. Tôi đã không thử điều này với Box2D nhưng nhìn chung có thể đạt được hành vi tương tự trên tất cả các máy trong một mô phỏng vật lý. Tất cả toán học thường dựa trên phao nhị phân IEEE 754 và hành vi của chúng được xác định nghiêm ngặt cho các hoạt động như +-*/đặt tên cho một số. Bạn cần phải cẩn thận về sin,cosvà thích rất khó, vì chúng có thể khác nhau giữa các thời gian chạy (điều này đặc biệt quan trọng khi phát triển cho nhiều nền tảng). Cũng đảm bảo rằng bạn sử dụng một cài đặt nghiêm ngặt để tối ưu hóa float trong trình biên dịch của bạn. Bạn vẫn có thể đồng bộ hóa các đối tượng bằng cách định kỳ gửi trạng thái của các đối tượng từ máy chủ. Đừng cập nhật trừ khi chênh lệch lớn hơn ngưỡng để tránh nói lắp không cần thiết.

Một vấn đề xuất hiện trong đầu là việc tạo ra các đối tượng mới và cách điều đó sẽ thay đổi mô phỏng giữa các khách hàng. Một cách để khắc phục điều này là cho phép máy chủ tạo tất cả các đối tượng. Nếu bước thời gian hiện tại là t, máy chủ sẽ lên lịch cho một đối tượng được thêm vào t+d. Do đó, một danh sách đối tượng mới, với các đối tượng cần thêm và khi nào cần thêm chúng, có thể được duy trì ở tất cả các máy khách và được máy chủ cập nhật trước. Nếu dđủ lớn, bạn giảm thiểu rủi ro của các kết quả khác nhau. Nếu bạn thực sự không thể xử lý sự khác biệt, bạn có thể buộc khách hàng chờ thông tin về các đối tượng mới trong một bước thời gian nhất định trước khi mô phỏng bước thời gian đó.


Cám ơn phản hồi của bạn. Tôi không nghĩ rằng box2d được đảm bảo tạo ra cùng một kết quả trên các CPU khác nhau, đó sẽ là kịch bản cho chúng tôi kể từ khi chúng tôi viết một trò chơi trên máy tính để bàn. Tôi hy vọng rằng sự khác biệt sẽ là phút và dễ dàng sửa chữa với các cập nhật định kỳ từ một máy chủ có thẩm quyền, nhưng tôi chưa bao giờ thử nó.
Venesectrix

Erin Catto nghĩ rằng việc cố gắng giữ cho toàn bộ trạng thái của nhiều thế giới Box2D đồng bộ là một trận thua ( box2d.org/forum/viewtopic.php?f=3&t=8462 )
Pavel

Câu lệnh "IEEE 754 binary32 float [..] hành vi được xác định nghiêm ngặt cho các hoạt động như +-*/" là hoàn toàn sai. Tất cả các hoạt động trong IEEE-754 có thể thay đổi dựa trên việc triển khai. Xem ở đâyở đây để biết thêm.
BlueRaja - Daniel Pflughoeft

1
Không. Điều đó hoàn toàn đúng. Vấn đề liên kết của bạn mô tả có liên quan đến các chế độ khác nhau của fpu x87 và việc triển khai siêu việt. IEEE 754 binary32 được xác định nghiêm ngặt cho các hoạt động cơ bản. Tùy thuộc vào bạn để đặt các chế độ chính xác và sử dụng đúng hướng dẫn để tiêu chuẩn được tuân theo. Đơn giản chỉ cần sử dụng các hướng dẫn SSE chứ không phải fpu x87 sẽ giúp ích rất nhiều.
rasmus

4

Có lẽ nó trông không được tốt lắm vì nội suy giữa chúng phụ thuộc vào việc luôn có bộ dữ liệu tiếp theo để nội suy. Điều này có nghĩa là, nếu có một độ trễ ngắn, mọi thứ phải chờ để bắt kịp.

một bài viết cũ trên GameDev về việc sử dụng các khối vuông để dự đoán vị trí của một vật thể qua điểm cuối cùng bạn có dữ liệu cho nó. Những gì bạn làm sau đó là sử dụng vị trí đó và sau đó điều chỉnh spline khi bạn nhận được dữ liệu mới để tính đến vị trí mới của nó. Nó cũng có thể rẻ hơn nhiều so với việc chạy một mô phỏng vật lý thứ hai, và điều đó có nghĩa là bạn không phải quyết định về người mà bạn tin tưởng, vì bạn đã triển khai rõ ràng ứng dụng khách tạo ra nó khi nó diễn ra. :)


Đây có thể là trường hợp. Những gì tôi đang cố gắng làm là trì hoãn cho đến khi tôi nhận được 3 ảnh chụp nhanh từ máy chủ. Tại điểm tôi lerp từ shot 1 đến shot 2. Sau đó từ shot 2 đến shot 3. Nếu tại bất kỳ thời điểm nào tôi bỏ lỡ một gói tôi có thể lerp từ 1 đến 3, thay vì 1 đến 2, nếu điều đó có ý nghĩa. Tôi có thể không được thực hiện chính xác mặc dù. Cảm ơn các liên kết đến bài viết!
Venesectrix

1

Tôi đã tự mình thực hiện một số thứ tương tự và tôi chỉ chạy Box2D trên các máy khách. Cách tôi đã làm là để máy khách tự chạy mô phỏng khá nhiều, gửi vận tốc hiện tại (và xoay) trên mỗi gói đồng bộ đến máy chủ. Sau đó, máy chủ sẽ gửi thông tin này cho những người chơi khác, những người đặt vận tốc mới nhận được cho các thực thể được nhân rộng. Nó rất trơn tru, không có sự khác biệt đáng chú ý giữa các khách hàng.

Tất nhiên, vấn đề ở đây là không có sự kiểm soát tập trung đối với các thực thể, nhưng tôi nghĩ điều đó cũng có thể được thực hiện ở phía máy chủ bằng cách thực hiện mô phỏng vật lý phía máy chủ.


Cảm ơn vì đầu vào của bạn. Chúng tôi sẽ yêu cầu kiểm soát tập trung để ngăn chặn gian lận, vì vậy chúng tôi phải có máy chủ chạy mô phỏng ít nhất để biết liệu những gì khách hàng nói họ đang làm là có thể hay không.
Venesectrix

1

Cá nhân tôi chỉ thích chạy các mô phỏng trên máy chủ và nó sẽ phát bất kỳ thay đổi nào về tốc độ / gia tốc tuyến tính / góc của các đối tượng liên quan bất cứ khi nào chúng xảy ra. Vì một lý do nào đó, vì một lý do nhất định, thay đổi bất kỳ thuộc tính vật lý nào của nó (chẳng hạn như tốc độ và gia tốc đã nói ở trên), thay đổi cụ thể này sẽ được gửi từ máy chủ đến máy khách và máy khách sẽ thay đổi bên cạnh dữ liệu của đối tượng phù hợp.

Ưu điểm của nó so với việc triển khai hiện tại của bạn là nó sẽ làm mất hiệu lực của sự nội suy của khách hàng và sẽ tạo ra một hành vi rất trung thành trên các đối tượng. Vấn đề là phương pháp này khá dễ bị ảnh hưởng bởi độ trễ, trở thành một vấn đề rất lớn khi người chơi ở quá xa về mặt địa lý.

Đối với câu hỏi 1, tôi nói rằng vấn đề sẽ là biến động về độ trễ, bởi vì không có gì đảm bảo tuyệt đối rằng sẽ có một khoảng thời gian 20 giây hoàn hảo chính xác giữa mỗi lần nhận ảnh chụp. Hãy để tôi minh họa (là "t" thời gian được tính bằng mili giây):

1) Khi t = 20 kể từ khi trò chơi bắt đầu, khách hàng đã nhận được một ảnh chụp nhanh và thực hiện nội suy thành công và trơn tru.

2) Tại t = 40, có độ trễ giữa máy chủ và máy khách và ảnh chụp nhanh chỉ thực sự đến t = 41.

3) Tại t = 60, máy chủ đã gửi một ảnh chụp nhanh khác, nhưng một giây mô phỏng đã bị lãng phí khách hàng vì độ trễ. Nếu ảnh chụp nhanh đến t = 60, khách hàng sẽ không thực hiện phép nội suy của 40 và 60 nội dung, mà thực tế là từ 41 đến 60, tạo ra một hành vi khác. Sự không chính xác này có thể là nguyên nhân của "sự giật" cuối cùng.

Đối với câu hỏi 2, ý tưởng của bạn có thể hoạt động nếu bạn triển khai một cái gì đó sẽ theo dõi hiệu quả xem mỗi đối tượng có thực sự được đồng bộ hóa máy chủ mà không phải gửi các gói mỗi khung thông báo vị trí của các đối tượng hay không. Ngay cả khi bạn làm điều đó trong các khoảng thời gian riêng biệt, bạn sẽ không chỉ chạy trên cùng một vấn đề của câu hỏi 1, mà còn có lượng dữ liệu quá lớn được chuyển xung quanh (đó là một điều xấu).


Tôi không chắc chắn tôi làm theo những gì bạn nói trong đoạn đầu tiên của bạn. Nếu mô phỏng chỉ chạy trên máy chủ và bạn chỉ phát các thay đổi về vận tốc / gia tốc thì làm thế nào để khách hàng biết được các họa tiết nên được vẽ ở đâu? Các khách hàng sẽ phải mô phỏng các vật thể dựa trên vận tốc / gia tốc nhận được để vẽ chúng đúng cách. Tôi nghĩ rằng bạn có thể đúng khi nhận được ảnh chụp nhanh trong khoảng thời gian khác với chính xác những gì tôi mong đợi. Bất cứ ý tưởng làm thế nào để đối phó với điều đó?
Venesectrix

Các máy khách biết vị trí ban đầu và hiện tại, tốc độ và gia tốc của các đối tượng và sẽ cập nhật vị trí mà nó nghĩ rằng các đối tượng (độc lập với máy chủ) tương ứng. Cuối cùng, máy chủ sẽ thay đổi các thuộc tính như vậy trên máy khách thông qua các tin nhắn, bởi vì đó là máy chủ đang thực hiện phát hiện va chạm vật lý (bắt buộc phải thay đổi tốc độ / gia tốc và hướng của đối tượng được đưa ra sớm hay muộn)
UBSophung 7/2
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.