Làm thế nào để đồng bộ hóa đồng hồ trong trò chơi nhiều người chơi?


8

Tôi có 2 đến 3 khách hàng, có thể trao đổi tin nhắn thông qua Apple Game Center.

Đồng bộ hóa duy nhất tôi cần là: bắt đầu trò chơi cùng một lúc.

Tôi đoán điều này liên quan đến đồng bộ hóa đồng hồ. Làm thế nào để thực hiện điều này?


3
Câu trả lời ngắn gọn là "bạn không thể". Sự chậm trễ không thể tránh khỏi (và không nhất quán) trong giao tiếp giữa các thiết bị có nghĩa là ngay cả khi một thiết bị nói 'Tôi tin rằng bây giờ là 12: 00: 00.00' thì nó có thể dễ dàng ở bất cứ đâu từ 12: 00: 00.10 đến 12:00:05 thời gian mà tin nhắn được nhận ở nơi khác Trong mô hình dựa trên máy chủ, bạn không thể làm tốt hơn nhiều so với việc máy chủ của bạn gửi tin nhắn 'Bắt ​​đầu trò chơi' cho khách hàng cùng một lúc.
Steven Stadnicki

Thật tốt khi tôi không cần sự hoàn hảo. Làm thế nào để làm điều đó tốt hơn không có gì? Có thể: mỗi người chơi gửi tin nhắn "BẮT ĐẦU" và bắt đầu ngay khi nhận được tin nhắn BẮT ĐẦU từ tất cả những người chơi khác
GameCoder

1
@StevenStadnicki Sự chậm trễ của mạng không làm cho điều này là không thể. Vấn đề chung được gọi là "đồng bộ hóa đồng hồ" và nó đã được nghiên cứu kỹ lưỡng. (Tuy nhiên, nếu bạn chỉ kiểm soát các điểm cuối, thì không thể tính đến sự bất cân xứng của độ trễ.)
Praxeolitic

Tôi có thể đang hiểu nhầm vấn đề của bạn, nhưng bạn có thể không chỉ làm cho tin nhắn bạn gửi cho khách hàng chỉ ra thời gian bắt đầu một chút trong tương lai không? Nếu thời gian là nowvà bạn gửi tin nhắn để bắt đầu chính xác now + halfSecondthì miễn là tất cả họ nhận được tin nhắn trong vòng nửa giây và miễn là đồng hồ hệ thống của họ được đồng bộ hóa chính xác, tất cả sẽ bắt đầu cùng một lúc.
Đánh dấu

Câu trả lời:


12

Nhận xét của Steven là đúng: về mặt lý thuyết là không thể làm được.

May mắn thay, trong thực tế, bạn có thể đến gần, đó là cách những thứ như NTP hoạt động.

Ví dụ, tốt hơn là chỉ gửi một tin nhắn cho 3 khách hàng nói rằng "bắt đầu ngay bây giờ", bạn có thể trao đổi một vài tin nhắn ping trước để đo thời gian nhận được tin nhắn cho khách hàng và khi bạn gửi tin nhắn bắt đầu, thay vì "bắt đầu ngay" hãy nói "bắt đầu sau X mili giây" và điều chỉnh X cho các thời điểm khác nhau được thực hiện để gửi tin nhắn.

ví dụ.:

  • Bạn gửi tin nhắn cho Khách hàng 1 và nhận được phản hồi sau 20ms. Bạn đoán rằng phải mất khoảng 10ms để nhận được tin nhắn cho khách hàng 1.
  • Bạn làm tương tự cho Client 2 và nhận được phản hồi 28ms sau - vì vậy thời gian truyền có thể là khoảng 14ms.
  • Vì vậy, bạn gửi tin nhắn cho Khách hàng 1 nói "bắt đầu trò chơi trong 50ms" và gửi một tin nhắn cho Khách hàng 2 nói "bắt đầu trò chơi trong 46ms". Khách hàng 2 sẽ nhận được thông báo khoảng 4ms sau, nhưng sẽ đợi 4ms ít hơn trước khi bắt đầu trò chơi.

Điều này không thể đảm bảo đồng bộ hóa vì thời gian gửi tin nhắn trên internet khác nhau và bởi vì nó có thể khác nhau theo từng hướng. Việc đầu tiên bạn có thể giảm các ảnh hưởng của bằng cách thực hiện phép đo nhiều lần và lấy số đọc trung bình. Thứ hai là khó hơn và về mặt lý thuyết là không thể giải quyết (mặc dù tôi không thể nhớ bằng chứng ngay bây giờ). Tin tốt là bạn có thể không cần độ chính xác cao như vậy.


Tôi có thể sẽ cần phải hạn chế hoạt động ứng dụng của mình trong quá trình đồng bộ hóa - ngay bây giờ tôi dành một chút thời gian CPU cho hệ thống con mạng ở mỗi khung vẽ. Nếu tốc độ khung hình là 30 FPS, thì tôi sẽ trả lời ping trong 1/30 = 33 ms. Tôi cũng có thể thêm 33 ms hoặc chênh lệch giữa "thời gian nhận ngăn xếp TCP" và MilisecondTicks hiện tại của tôi () ..
GameCoder

2
Nếu bạn đang hy vọng giữ cho các hệ thống được đồng bộ hóa chính xác từng khung hình trong khi chơi, tôi nghĩ đó là một trò chơi thua và bạn nên từ bỏ ngay bây giờ. Đồng hồ và độ trễ sẽ trôi và thông tin sẽ luôn mất thời gian để đi du lịch. Dù bạn đang cố gắng làm gì, có lẽ bạn không cần mức độ đồng bộ hóa này.
Kylotan

Tôi nghĩ rằng chúng ta đang thiếu điểm. Đó không phải là sự hoàn hảo làm phiền tôi, đó là trải nghiệm người dùng. Điều này có thể tốt hoặc tốt hơn, và tôi muốn tốt hơn. Đó là nó.
GameCoder

2
Trải nghiệm người dùng tốt không yêu cầu đồng bộ hóa chính xác. Đó là lý do tại sao hầu hết các trò chơi không thử nó.
Kylotan

1
Về mặt lý thuyết là không thể nếu mỗi người chơi điều khiển con dơi của mình, bởi vì phải mất một khoảng thời gian khác không để thông tin đó đến được máy tính khác, trong đó hai bên có thông tin khác nhau. Thay vào đó bạn tìm cách đối phó với sự khác biệt. Vấn đề của bạn không thực sự khác biệt so với bất kỳ trò chơi trực tuyến có nhịp độ nhanh nào khác và có một số câu hỏi khác về cách xử lý kết nối mạng cho họ trên trang web này. Một người ở đây: gamedev.stackexchange.com/questions/22444/
Kẻ

3

Như đã đề cập, điều này là không thể, vì vậy tôi sẽ thử một cách tiếp cận khác:

Nếu bạn không có máy chủ chuyên dụng, hãy chọn một khách hàng tham gia để trở thành máy chủ lưu trữ (điều này có thể được chuyển nếu có nhu cầu).

Giờ đây, máy chủ sẽ thực hiện tất cả logic trò chơi quan trọng, như phát hiện lần truy cập, điều khiển AI, xử lý kho, v.v. cũng như theo dõi thời gian (tức là chỉ định thời gian trò chơi).

Các khách hàng khác sẽ chỉ cố gắng đồng bộ hóa với máy chủ, cố gắng ước tính hoặc xấp xỉ giá trị mong đợi. Nếu độ trễ tăng hoặc mất gói, mọi thứ có thể trở nên khó khăn, nhưng việc bắt kịp, về cơ bản chỉ là chờ đợi bản cập nhật tiếp theo.

Hầu hết các trò chơi (đặc biệt là FPS) che giấu sự thật này bằng cách thực hiện tính toán cục bộ của riêng họ cho chuyển động của chính người chơi, các phát bắn, v.v. để tránh trò chơi cảm thấy bị lag. Mọi thứ vẫn được sửa dựa trên dữ liệu máy chủ. Điều này có thể dẫn đến một số nhầm lẫn, ví dụ như bạn thấy mình bắn kẻ thù, nhưng cùng lúc bạn chết (không có kẻ địch bị bắn trúng), nhưng nó vẫn là một cách tiếp cận tốt hơn nhiều so với đồng bộ hóa hoàn toàn.


Nếu bạn vẫn khăng khăng giữ mọi thứ đồng bộ, có lẽ bạn muốn tạo một loại bộ đếm bước hoặc khung, vì vậy tất cả khách hàng chỉ xử lý một bước logic, sau đó đồng bộ hóa dữ liệu của họ, v.v. Hãy nhớ rằng đây có thể là cả băng thông chuyên sâu cũng như độ trễ, vì vậy tôi không khuyên bạn nên làm điều đó trừ khi bạn có nhiều dữ liệu khác và lối chơi của bạn dựa trên lượt (ví dụ: trò chơi theo phong cách Pháo binh / Giun).


1

Tôi khuyên bạn nên đồng bộ hóa bộ định thời hệ thống trên tất cả các máy khách và máy chủ bằng giao thức NTP [Stratum 2], sau đó máy chủ sẽ gửi lệnh để bắt đầu trò chơi vào thời gian được chỉ định, khi tất cả các bộ định thời đạt 0:05:00. Cách tiếp cận này sẽ cung cấp cho bạn 3-4 ms đồng bộ hóa chính xác, tôi 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.