Misalnya permainan Flappy Bird yang terkenal, atau apa pun yang benar-benar menyortir, adalah pemain (dalam hal ini burung, atau kamera mana pun yang Anda suka) bergerak maju atau seluruh dunia bergerak mundur (burung hanya mengubah posisi Y dan memiliki posisi X konstan)?
game-mechanics
platformer
Lendrit Ibrahimi
sumber
sumber
Jawaban:
Saya sedikit tidak setuju dengan jawaban Philipp ; atau setidaknya dengan bagaimana dia mempresentasikannya. Ini memberi kesan bahwa menggerakkan dunia di sekitar pemain mungkin ide yang lebih baik; padahal justru sebaliknya. Jadi, inilah jawaban saya sendiri ...
Kedua opsi dapat bekerja, tetapi umumnya merupakan ide yang buruk untuk "membalikkan fisika" dengan menggerakkan dunia di sekitar pemain daripada pemain di seluruh dunia.
Kehilangan / pemborosan kinerja:
Dunia biasanya akan memiliki banyak objek; banyak jika tidak sebagian besar, statis atau tidur. Pemain akan memiliki satu, atau relatif sedikit, objek. Memindahkan seluruh dunia di sekitar pemain, berarti memindahkan semua yang ada di adegan kecuali pemain. Objek statis, objek dinamis tidur, objek dinamis aktif, sumber cahaya, sumber suara, dll; semua harus dipindahkan.
Itu (jelas) jauh lebih mahal daripada hanya memindahkan apa yang sebenarnya bergerak (pemain, dan mungkin beberapa hal lagi).
Maintabilitas & Ekstensibilitas:
Menggerakkan dunia di sekitar pemain membuat dunia (dan semua yang ada di dalamnya) menjadi titik di mana hal-hal yang paling aktif terjadi. Setiap bug atau perubahan dalam sistem berarti bahwa, berpotensi, semuanya berubah. Ini bukan cara yang baik untuk melakukan sesuatu; Anda ingin bug / perubahan terisolasi sebanyak mungkin, sehingga Anda tidak mendapatkan perilaku tak terduga di suatu tempat yang belum Anda lakukan perubahan.
Ada juga banyak masalah lain dengan pendekatan ini. Sebagai contoh, itu mematahkan banyak asumsi tentang bagaimana segala sesuatu seharusnya bekerja di dalam mesin. Anda tidak akan dapat menggunakan dinamis
RigidBody
untuk apa pun selain pemain, misalnya; sebagai objek dengan lampiran yangRigidBody
tidak disetel ke kinematik akan berperilaku tak terduga ketika mengatur posisi / rotasi / skala (yang akan Anda lakukan setiap frame, untuk setiap objek dalam adegan, kecuali pemain 😨)Jadi jawabannya adalah memindahkan pemain saja!
Ya ... ya dan tidak . Seperti yang disebutkan dalam jawaban Philipp, dalam jenis game pelari tak terbatas (atau game apa pun dengan area eksplorer besar yang mulus), terlalu jauh dari asalnya pada akhirnya akan memperkenalkan FPPE yang terlihat ( Floating-Point Precision Errors ), dan lebih jauh lagi, akhirnya, melimpahi tipe numerik, baik menyebabkan game Anda crash, atau, pada dasarnya, membuat asap-dunia permainan retak ... Pada steroid! 😵 (karena pada titik ini, FPPEs akan membuat gim tersebut sudah berada pada celah "normal")
The aktual solusi:
Jangan melakukan keduanya dan lakukan keduanya! Anda harus menjaga dunia tetap statis, dan menggerakkan pemain di sekitarnya. Tapi "re-root" baik , pemain dan dunia, ketika pemain mulai terlalu jauh dari akar (posisi
[0, 0, 0]
) adegan.Jika Anda mempertahankan posisi relatif barang (pemain dengan dunia di sekitarnya), dan melakukan proses ini dalam satu pembaruan bingkai, pemain (sebenarnya) bahkan tidak akan menyadarinya!
Untuk melakukannya, Anda memiliki dua opsi utama:
Berikut adalah contoh dari proses ini dalam tindakan
Tapi, seberapa jauh terlalu jauh?
Jika Anda melihat kode sumber Unity, mereka menggunakan
1e-5
(0.00001
) sebagai dasar untuk mempertimbangkan dua nilai titik-mengambang "sama", di dalamVector2
danVector3
(tipe-data yang bertanggung jawab atas posisi objek, rotasi dan skala [euler-]). Karena kehilangan presisi floating-point terjadi jauh dari nol, aman untuk mengasumsikan bahwa apa pun di bawah1e+5
(100000
) unit yang jauh dari tempat asal / asal aman untuk digunakan.Tapi! Sejak...
... maka mungkin ide yang bagus untuk melakukan root ulang lebih cepat / lebih sering daripada tanda 100000 unit. Contoh video yang saya berikan tampaknya melakukannya setiap 1000 unit atau lebih, misalnya.
sumber
Kedua opsi berfungsi.
Tetapi jika Anda ingin pelari tanpa akhir menjadi benar-benar tidak ada habisnya, Anda harus menjaga stasioner pemain dan menggerakkan dunia. Kalau tidak, Anda pada akhirnya akan mencapai batas variabel yang Anda gunakan untuk menyimpan posisi-X. Integer pada akhirnya akan meluap dan variabel floating point akan menjadi semakin kurang akurat yang akan membuat gameplay menjadi glitchy setelah beberapa saat. Tetapi Anda dapat menghindari masalah ini dengan menggunakan tipe yang cukup besar sehingga tidak seorang pun akan menghadapi masalah ini dalam rentang waktu yang bisa dimainkan dalam satu sesi (ketika seorang pemain bergerak 1000 piksel per detik, bilangan bulat 32 bit akan meluap setelah 49 hari).
Jadi, lakukan apa pun yang secara konseptual terasa lebih intuitif bagi Anda.
sumber
Membangun jawaban XenoRo , alih-alih metode rooting ulang yang mereka gambarkan, orang bisa melakukan yang berikut:
Buat penyangga bundar bagian-bagian dari peta tak terbatas Anda yang dihasilkan, yang karakter Anda bergerak dengan posisi diperbarui dengan modulo aritmatika (sehingga Anda hanya berjalan di sekitar penyangga melingkar). Mulailah mengganti bagian-bagian buffer Anda segera setelah karakter Anda meninggalkan bagian. Persamaan pembaruan pemain akan menjadi seperti:
player.position = (player.position + player.velocity) % worldBuffer.width;
di sini adalah contoh gambar dari apa yang saya bicarakan:
Berikut adalah contoh dari apa yang terjadi pada pembungkus di bagian akhir.
Dengan metode ini Anda tidak pernah mengalami kesalahan presisi, tetapi Anda mungkin perlu membuat buffer yang sangat besar jika Anda berniat melakukan ini dalam 3d dengan jarak pandang sangat jauh (karena Anda masih harus dapat melihat ke depan sendiri) ). Jika flappy bird ukuran chunk Anda mungkin hanya akan sebesar yang diperlukan untuk memegang satu adegan untuk satu layar, dan buffer Anda bisa sangat kecil.
Perhatikan bahwa Anda akan mulai mendapatkan hasil berulang dengan APA PUN , dan jumlah maksimum urutan berulang dari generasi PRNG biasanya kurang dari panjang pow (2, jumlah bit yang digunakan secara internal), dengan merzenne twister ini bukan banyak masalah, karena menggunakan 2.5k keadaan internal, tetapi jika Anda menggunakan varian kecil, Anda memiliki iterasi 2 ^ 127-1 maks sebelum diulang (atau lebih buruk), ini masih merupakan jumlah yang sangat besar secara astronomi . Anda dapat memperbaiki masalah periode berulang bahkan jika PRNG Anda memiliki periode singkat melalui fungsi pencampuran longsoran yang baik untuk seed (saat Anda menambahkan lebih banyak status secara implisit) berulang kali.
sumber
Seperti yang sudah ditanyakan dan diterima, itu benar-benar tergantung pada ruang lingkup dan gaya permainan Anda, tetapi karena tidak disebutkan: FlappyBird memindahkan penghalang di layar, daripada pemain di seluruh dunia.
Seorang spawner adalah instantiating objek dari layar dengan kecepatan tetap di
Vector2.left
arahsumber