Saya menerapkan MMO di mana pemain terbang di angkasa pada kapal luar angkasa mengendalikannya dengan tombol panah dan bekerja sama dengan pemain lain.
Saya ingin mengimplementasikannya sehingga pemain akan dapat menghindari kapalnya dari roket atau sesuatu yang lain, jadi saya mencoba untuk memprediksi seluruh kondisi permainan di sisi klien menggunakan algoritma simulasi dunia yang sama seperti penggunaan server. Dunia permainan itu ditulis pada C # dan akan dipanggil dalam klien secara langsung (ditulis di Unity3D) dan melalui CLR pada server C ++ (di Linux). Koneksi melalui UDP.
Masalahnya adalah bagaimana mempertahankan, misalnya, 1000 pemain dalam satu peta (tidak termasuk semua objek game lainnya, massa ...): Katakanlah saya akan:
- sinkronisasi server dengan klien 50 kali per detik
- kirim ke setiap negara klien hanya dari objek permainan (dan pemain) yang dapat dilihatnya (dalam beberapa radius)
- harus mengirim 100 objek ke setiap pemain dalam radius pandangannya
- harus mengirim rata-rata 50 byte per objek game (itu id, x, y coords, rotasi, status ...)
jadi, perlu memiliki bandwidth jaringan seperti itu: 1000 (klien) * 50 (kali per detik) * 100 (objek untuk dikirim ke setiap pemain) * 50 (byte per objek) = 250.000 000 byte per detik! Tidak mungkin!
Apakah mungkin mengurangi nilai ini? Sebagai contoh, biarkan klien untuk sepenuhnya mensimulasikan dunia game mereka (untuk jangka waktu yang lama) dan mengirim mereka hanya input dari klien lain dan menyinkronkan dunia game, katakanlah, setiap beberapa detik tetapi itu akan menyebabkan masalah desinkronisasi yang aneh pada leash karena perhitungan float .
Ngomong-ngomong, bagaimana game seperti itu diprogram secara umum? Terima kasih.
sumber
Jawaban:
Anda hanya membutuhkan sekitar 30 pembaruan (atau bahkan kurang dari 10 atau 20) per detik. interpolasi posisi objek yang bergerak di sisi klien. Secara umum Anda hanya boleh mengirim data ketika itu SANGAT dibutuhkan. Di WoW Anda mungkin menerima lebih banyak pembaruan dari para pemain yang berada dalam grup dengan Anda daripada dari para pemain yang berada di lokasi yang sama. Juga, jika pemain lain jauh dari Anda, Anda tidak menerima banyak pembaruan per detik tentang dia.
Kemudian, hanya kirim satu snapshot lengkap ke setiap pemain saat dia terhubung. Setelah itu hanya mengirim perubahan objek game. Jika tidak ada perubahan, jangan kirim.
Kemudian, gunakan BitVectors dengan berat atau setiap kali Anda memanggilnya untuk mengurangi jumlah data yang tidak dibutuhkan! Contoh: Anda juga dapat mencoba menulis float menggunakan hanya satu byte (dalam rentang dari 0 hingga 1 atau -1 hingga 1) sehingga Anda hanya memiliki 256 atau 128 nilai yang berbeda. Tapi pemain tidak akan melihat gerakan tersentak-sentak berkat interpolasi.
Lihat ini sebagai contoh dengan LidgrenLibrary tentang cara mengompres data: http://code.google.com/p/lidgren-network-gen3/wiki/Optimization
Berikutnya: Coba kurangi radius tampilan pemain saat mereka bergerak, dan hanya kirimkan informasi penting pada waktu itu. Kemudian ketika mereka berhenti meningkatkan radius tampilan mereka lagi. Anda dapat menggunakan sistem hashing spasial atau pohon bsp untuk mengurangi overhead mencari objek yang "dalam jangkauan". Ini adalah bacaan yang bagus untuk topik: http://en.wikipedia.org/wiki/Collision_detection
Kompres data DIRI ANDA sendiri hanya ANDA yang tahu tentang struktur data dan koherensi temporal dalam data (yang dapat dan harus dieksploitasi). Algoritma umum seperti Bzip2, Deflate, apa pun, harus digunakan, tetapi hanya sebagai tahap akhir kompresi!
Selain itu, untuk informasi yang tidak penting untuk permainan, Anda juga bisa menggunakan teknik P2P tambahan. Contoh: Seorang pemain memainkan animasi "halo". (Hanya efek grafis) Pemain mengirim informasi ini ke server, tetapi server tidak menyampaikan informasi tersebut ke pemain lain. Alih-alih ini efek non-kritis dikirim oleh pemain itu sendiri ke klien lain dalam jangkauan.
EDIT (karena komentar):
Metode tambahan untuk mengurangi jumlah bit rata-rata per detik untuk setiap pemain:
Anda menulis bahwa Anda mengirim "Objek tidak berubah". Tidak ada alasan untuk melakukan ini. Jika Anda khawatir tentang kehilangan paket (dan membuat simulasi Anda tidak sinkron karena hal ini) pertimbangkan hal berikut: Pada setiap catatan waktu tetap (mis. 100, 200, 300, 400 ...) hash kondisi simulasi dan kirimkan ke server . server mengkonfirmasi atau mengirim snapshot lengkap dari semua data kembali.
Untuk hal-hal seperti roket atau bahkan pemain Anda dapat menggunakan tidak hanya interpolasi tetapi juga ekstrapolasi untuk membuat simulasi lebih realistis. Contoh 'Rocket': Alih-alih memperbarui dengan pesan seperti "Apakah sekarang di posisi x" hanya mengirim pesan sekali berisi yang berikut: "Rocket Spawned: position (vector), Time (di mana simulasi langkah roket itu muncul), kecepatan ( vektor) ". Jadi Anda bahkan tidak perlu memasukkan rotasi karena ujungnya akan selalu berada di arah "kecepatan".
Gabungkan beberapa perintah dalam satu pesan dan jangan pernah mengirim pesan yang lebih kecil dari 16-20 byte karena header udp akan lebih besar dari pesan itu sendiri. Juga jangan mengirim paket yang lebih besar dari MTU protokol Anda karena fragmentasi akan memperlambat kecepatan transmisi.
sumber
Berikut ini dua pendekatan:
Pertama:
Beralih ke fisika deterministik, mengirim perintah pemain, tindakan ai, objek yang terlihat dan apa pun yang tidak dapat ditentukan sisi klien ke klien. Ini harus menyertakan non-perintah, konfirmasi bahwa hingga titik waktu tertentu tidak lain adalah perintah yang telah dikirim dan diterima berlaku.
Klien harus menjalankan dua atau tiga simulasi simultan.
1: Menghentikan setiap kali ada data yang hilang untuk langkah selanjutnya.
2: Lanjutkan menggunakan data dugaan dan berikan status yang digunakan untuk rendering. 3: Setiap kali no 1 menghentikan simulasi ini menyalin keadaan no 1, mengejar waktu saat ini dan mengambil alih untuk no 2, yang kemudian dijatuhkan.
Jika mengejar cukup cepat Anda dapat meninggalkan perbedaan antara no 2 dan no 3 dan langsung drop data lama.
Kedua:
Jangan gunakan fisika deterministik, lakukan hal yang sama seperti di atas, tetapi kirim "frame penuh" sekali setiap beberapa detik. Anda dapat dengan mudah meninggalkan transfer hal-hal sementara seperti peluru.
Dalam kedua kasus ini, Anda mungkin ingin waspada dengan klien yang memprediksi siapa saja yang sekarat, agak konyol melihat lawan yang tidak meledak.
Dan +1 untuk perhitungan matematika, terlalu banyak orang gagal membuat estimasi penggunaan sumber daya sederhana.
sumber
Beberapa pertanyaan dulu.
Apakah 'roket atau sesuatu yang lain' cerdas atau bodoh? Jika mereka bodoh, yang Anda butuhkan hanyalah cap waktu api, asal, dan vektor untuk mensimulasikan lintasan mereka. Jika mereka cerdas, seberapa pintar mereka? Bisakah Anda menghitung pada saat kebakaran itu mereka akan mengenai atau meleset? Jika demikian, Anda dapat mensimulasikan seluruh jalur pada klien. ("Pada T13 rudal akan mengenai kapal karena permainan kehilangan dodge roll / penembak mencetak hit kritis.")
Secara umum meskipun tidak ada banyak alasan untuk: A) memiliki clock rate 50Hz, (Kebanyakan penembak lolos dengan 15-20 dan MMO kurang dari itu.) B) mengirim keadaan penuh setiap frame. (Apakah rotasi rudal di ruang angkasa sama sekali? Atau bisakah Anda mengasumsikan bahwa 'depan' diorientasikan sepanjang vektor yang dilalui?)
Habiskan waktu dengan prediksi dan interpolasi, dan Anda akan melihat bandwidth Anda anjlok. Sebuah proyek yang saya kerjakan memiliki tingkat pembaruan 10Hz, dan representasi keadaan objek saya pikir 14 byte. (Kompres semua yang Anda bisa! Saya percaya kami menggunakan 6 bit untuk menentukan rotasi di sekitar bidang x dan kemudian 6 bit lainnya untuk kemiringan di atas / di bawah bidang itu, itu terlihat tidak dapat dibedakan dengan mengirimkan matriks rotasi / angka empat yang sebenarnya.)
Hal lain yang dapat Anda lakukan adalah memprioritaskan objek. Tunjukkan, mungkin ada 100 objek di set yang relevan, tetapi apakah Anda tahu pandangannya frustrasi di server? Jika sesuatu tidak ada dalam pandangannya, bisakah Anda menghentikan frekuensi pembaruannya dengan urutan besarnya?
Gagasan umum bukan untuk membuat simulasi yang sempurna pada klien, itu tidak mungkin, idenya adalah membuat permainan yang menyenangkan di mana para pemain tidak akan melihat bahwa itu bukan simulasi yang sempurna.
sumber