Bagaimana cara menyinkronkan jam di jaringan untuk pengembangan game?

10

Saya sedang menulis game yang memiliki banyak aspek berbasis waktu. Saya menggunakan waktu untuk membantu memperkirakan posisi pemain ketika jaringan berhenti dan paket tidak melalui (dan waktu antara paket diterima dan tidak). Ini adalah jenis permainan pacman dalam arti bahwa seorang pemain memilih arah dan tidak bisa berhenti bergerak, sehingga sistem masuk akal (atau setidaknya saya pikir itu bisa).

Jadi saya punya dua pertanyaan: 1) Bagaimana cara menyinkronkan jam dari permainan di awal karena ada keterlambatan dalam jaringan. 2) Apakah boleh BUKAN untuk menyinkronkannya dan hanya berasumsi bahwa semuanya sama (kode saya tidak tergantung pada zona waktu). Ini bukan game yang sangat kompetitif di mana orang akan mengubah jam mereka menjadi curang, tapi tetap saja.

Gim ini diprogram dalam Java dan Python (pengembangan paralel sebagai proyek)

dosaθ
sumber
7
lihat ntp
ratchet freak
5
Saya yakin pertanyaan ini sudah dibahas di gamedev.stackexchange.com, atau setidaknya itu milik di sana.
congusbongus
1
@CongXu: Saya tidak begitu yakin. Meskipun ini biasanya tugas yang dilakukan untuk game, itu tidak secara inheren khusus untuk pengembangan game. Banyak sistem terdistribusi lainnya membutuhkan sinkronisasi jam.
Jan Hudec
2
Sudahkah Anda mencoba menggunakan opsi IPv4 TIMESTAMP? Info lebih lanjut ada di linux.die.net/man/7/socket dari sana ke linux.die.net/man/3/cmsg dan kemudian contoh program kecil di pdbuchan.com/rawsock/rawsock.html yang terakhir sebelum Bagian IPv6.
ott--
2
Game (aplikasi) tidak boleh menyentuh jam sistem.
Pasang kembali Monica - M. Schröder

Jawaban:

9

Saya pikir sudah pasti tidak baik untuk menyinkronkan jam dalam sistem . Pengguna tidak berharap Anda menyentuh pengaturan sistem dan banyak sistem bahkan tidak akan membiarkan Anda melakukannya.

Yang Anda butuhkan hanyalah memiliki korelasi untuk mengubah timestamp dari jam satu sisi ke jam pihak lain. Di sisi lain Anda perlu korelasi ini agak tepat, katakan setidaknya seperseratus detik, jika Anda ingin menggunakannya untuk memprediksi posisi pemain. Jam sistem tidak akan pernah berkorelasi dengan baik antara mesin acak ini. Jadi, Anda harus membuat korelasinya sendiri, menggunakan beberapa variasi pada tema NTP , mungkin tertanam dalam pesan Anda yang lain untuk menghemat bandwidth jaringan.

Ide dasarnya mungkin bahwa dengan setiap paket yang Anda kirim timestamp yang Anda kirim dan nomor urut dan timestamp ketika Anda menerima paket terakhir dari sisi lain. Dari ini Anda menghitung pulang pergi: Misalnya jika paket Q mengatakan itu dikirim pada 1000 dan paket P diterima pada 500, daripada memberi Anda mengirim paket P pada 0 dan menerima Q pada 800, round-trip adalah (800 - 0 ) - (1000 - 500) = 300. Tidak ada cara untuk mengetahui asimetri, sehingga Anda hanya berasumsi bahwa paket tersebut mengambil setengah (150) kutu di kedua arah. Dan stempel waktu jauh lebih cepat dari lokal dengan 1000 - (800 - 150) = 350 ticks. Perjalanan pulang pergi akan bervariasi. Jika Anda menganggap jam itu cukup tepat, Anda harus menggunakan rata-rata korelasi jangka panjang.

Perhatikan, Anda juga tidak ingin menggunakan jam sistem untuk jam tersebut. Mereka mungkin disinkronkan di tengah jalan, membuat Anda keluar jalur. Anda harus menggunakan clock(CLOCK_MONOTONIC)Unix atau GetTickCountWindows (tidak yakin bagaimana API tersebut dibungkus dengan Java atau Python sekarang).


Catatan: SO_TIMESTAMPOpsi soket (lihat soket (7) yang disebutkan oleh ott-- dalam mengomentari pertanyaan) akan berguna untuk memisahkan efek latensi dari loop peristiwa yang menerima paket. Apakah itu sepadan dengan usaha tergantung pada seberapa baik presisi yang Anda butuhkan.

Jan Hudec
sumber
1

Bagaimana Anda tahu jam pemain mana yang benar? Anda tidak, jadi gunakan jam referensi .

NTP berlebihan di sini - Anda hanya perlu ~ 1 detik akurasi - jadi gunakan rdate atau pilih sesuatu dari salah satu dari banyak algoritma sinkronisasi jam.

Jika Anda telah memilih metode, minta mesin setiap pemain untuk mengambil waktu per metode itu (tanpa mengubah jam sistem mereka). Apa pun perbedaan ada di antara waktu UTC referensi dan jam sistem pemain waktu UTC adalah offset efektif mereka. Setiap kali Anda melakukan perhitungan yang berkaitan dengan waktu untuk mis memperkirakan pergerakan bot atau peluru ray-trace, Anda memperhitungkan offset ini setelah mendapatkan waktu sistem. Menggunakan UTC akan menghilangkan faktor zona waktu.

JBRWilkinson
sumber
1

Saya menyatakan kedua bahwa Anda tidak boleh menggunakan NTP atau mendekati jam sistem untuk ini. Jika Anda benar-benar memeriksa persyaratan ini, Anda akan menemukan bahwa Anda memiliki kebutuhan berikut:

  • Berapa banyak waktu yang telah berlalu sejak frame sebelumnya sehingga Anda dapat memajukan hal-hal berbasis waktu. Ini mungkin berbeda pada klien dan server jika keduanya mencentang pada tingkat yang berbeda (misalnya Anda kadang-kadang melihat server yang berjalan pada 20Hz tetap (atau apa pun) tetapi klien yang diizinkan untuk berlari secepat yang mereka inginkan).
  • Berapa banyak waktu yang telah berlalu sejak peta saat ini dimulai. Ini adalah timer berbasis nol (cukup init ke 0 pada klien dan server ketika mereka mulai) dan waktu server dianggap sebagai "master", sehingga server mengirimkan tampilan saat ini ke klien untuk setiap frame yang berjalan di server. Ini bisa didapat dengan mengambil waktu server saat ini dan mengurangi waktu di mana server mulai, atau dengan mengakumulasi waktu per-frame di atas. Waktu per-frame sisi klien di atas juga dapat digunakan untuk menghasilkan titik interpolasi antara dua frame server berurutan.
  • Referensi "waktu dasar" dari mana semua waktu lainnya maju; ini bisa (tetapi tidak mutlak harus untuk semua jenis game) yang sama di kedua klien dan server dan diinisialisasi pada awal permainan (atau peta saat ini) tetapi tidak pernah berubah setelah (kecuali permainan baru - atau peta baru - dimulai).

Ini adalah garis besar yang disederhanakan - Saya tidak berusaha untuk menangani masalah-masalah seperti latensi / paket yang dijatuhkan / dll - tetapi ini adalah kerangka dasar di mana semuanya harus didasarkan.

Tidak satu pun dari ini perlu mendekati jam sistem atau peduli dengan hal-hal seperti zona waktu yang berbeda, meskipun item terakhir dapat menggunakan zona waktu jika diinginkan. Yang penting adalah waktu aktual yang berlalu diukur menggunakan timer berbasis nol resolusi tinggi, sehingga mereka benar-benar agnostik terhadap perbedaan zona waktu. Ingin menemukan waktu aktual saat ini di server? Tambahkan saja sudah waktunya untuk referensi waktu dasar dan Anda sudah mendapatkannya. Demikian juga untuk klien.

Maximus Minimus
sumber