Perbedaan antara metode Pembaruan dan FixedUpdate di Unity?

14

Saya mulai belajar Unity3d dan salah satu kebingungan yang saya dapatkan adalah perbedaan antara Update()dan FixedUpdate().

Saya mengikuti tutorial pengembangan game Lynda Unity 2D di sana, instruktur menggunakan Updatemetode, pemain memiliki komponen RigidBody2D dan Box collider, ia menggunakan Updatemetode untuk menerjemahkan pemain, tetapi ketika saya melakukan hal yang sama di Updatepemain tidak bergerak tetapi ketika saya melakukannya itu FixedUpdate, semuanya bekerja. Dia memberikan tutorial dari Unity 4.3 dan saya mengambil kursus di Unity 4.6.

Di mana saya harus menggunakan Updatedan FixedUpdate?

biarawan
sumber

Jawaban:

14

Saya akan menulis ini sebagai komentar, tetapi akhirnya menjadi agak panjang lebar jadi saya mengubahnya menjadi jawaban.

Jawaban saat ini sebagian besar benar, tetapi beberapa hal yang disebutkan menyesatkan / salah.

Secara umum, sebagian besar tugas terkait permainan akan masuk Update.

Misalnya, Anda tidak ingin polling untuk input FixedUpdate(bukan karena kinerja, tetapi karena panggilan tidak akan berfungsi dengan benar). AI jatuh di kapal yang sama.

Fisika yang terus diperbarui adalah satu - satunya tugas terkait gameplay yang FixedUpdateharus digunakan. Panggilan tidak kontinu / sesekali untuk hal-hal seperti Physics.Raycast, atau bahkan Rigidbody.AddForcetermasuk Update. Penyebutan saya Rigidbody.AddForcetampaknya bertentangan dengan apa yang mungkin tersirat oleh dokumentasi, tetapi kuncinya adalah Kontinu vs Non-kontinu.

Salah satu alasan besar mengapa hanya fisika kontinu yang termasuk dalam FixedUpdateadalah sifat sebenarnya FixedUpdate. Jawaban lain telah menyebutkan bagaimana FixedUpdate disebut pada fixed interval, but that's slightly misleading. In reality, a script is passed a time in Time.deltaTime/ Time.fixedDeltaTime* yang tidak berhubungan langsung dengan waktu aktual antar panggilan, melainkan waktu simulasi antar panggilan.

(* Time.deltaTimedan Time.fixedDeltaTimememiliki nilai yang sama ketika dipanggil FixedUpdate[Unity dapat mengetahui apakah panggilan saat ini Time.deltaTimeberasal selama FixedUpdatedan kembali Time.fixedDeltaTime])

Secara alami cara yang sama Updatetidak dapat dipanggil secara konstan karena kinerja yang bervariasi, juga tidak bisa FixedUpdate. Perbedaan utama adalah, setiap frame, jika FixedUpdatebelum dipanggil cukup sering untuk rata-rata ke interval yang benar antara panggilan, itu dipanggil beberapa kali (atau tidak disebut rata-rata terlalu tinggi). Inilah yang dirujuk oleh dokumen tentang Perintah Eksekusi dengan mengatakan bahwa FixedUpdate dapat disebut beberapa kali dalam satu frame:

... FixedUpdate: FixedUpdate sering disebut lebih sering daripada Pembaruan. Ini dapat disebut beberapa kali per frame, jika frame rate rendah dan mungkin tidak dipanggil antara frames sama sekali jika frame rate tinggi ...

Ini tidak mempengaruhi Fisika karena sifat dari sisa urutan eksekusi dan mesin, tetapi apa pun yang Anda masukkan FixedUpdateakan terpengaruh, dan itu akan menyebabkan masalah.

Misalnya, jika Anda memasukkan pemrosesan AI ke dalam, FixedUpdatetidak ada alasan untuk menganggap bahwa AI tidak akan melewatkan pembaruan untuk beberapa frame secara berturut-turut. Selain itu, setiap kali `FixedUpdate tertinggal, AI Anda akan diperbarui beberapa kali dalam satu frame sebelum hal-hal seperti input dan pergerakan pemain diproses, yang merupakan pemborosan pemrosesan paling tidak, tetapi juga sangat mungkin menyebabkan hard untuk melacak bug dan perilaku tidak menentu.

Jika Anda perlu melakukan sesuatu pada interval tetap gunakan metode lain Unity menyediakan seperti Coroutinesdan InvokeRepeating.

Dan catatan kecil di Time.deltaTimedan kapan menggunakannya:

Cara termudah untuk menggambarkan efek Time.deltaTime adalah mengubah angka dari unit per frame, ke unit per detik . Misalnya, jika Anda memiliki skrip dengan sesuatu seperti transform.Translate(Vector3.up * 5)di Pembaruan, Anda pada dasarnya memindahkan transformasi dengan kecepatan 5 meter per frame . Itu berarti jika framerate rendah gerakannya lebih lambat, dan jika framerate tinggi, gerakannya lebih cepat.

Jika Anda mengambil kode yang sama dan mengubahnya transform.Translate(Vector3.up * 5 * Time.deltaTime), objek dipindahkan dengan kecepatan 5 meter per detik . Itu berarti tidak peduli framerate, objek akan bergerak 5 meter setiap detik (tetapi semakin lambat framerate, semakin lompat pergerakan objek akan muncul karena masih bergerak dalam jumlah yang sama setiap X detik)

Secara umum, Anda ingin gerakan Anda menjadi per detik. Dengan cara itu, tidak peduli berapa kecepatan komputer berjalan, fisika / gerakan Anda akan berperilaku dengan cara yang sama, dan Anda tidak akan menemukan bug aneh muncul di perangkat yang lebih lambat.

Dan tidak ada gunanya menggunakannya FixedUpdate. Karena apa yang saya sebutkan di atas, Anda akan mendapatkan nilai yang sama setiap panggilan (nilai Pembaruan Tanda Waktu Tetap), dan tidak akan melakukan apa pun terhadap nilai Anda. Gerakan / Fisika yang didefinisikan dalam FixedUpdateakan menjadi dalam satuan per detik sehingga Anda tidak membutuhkannya.

Selali Adobor
sumber
4

The Updatefungsi disebut setiap frame. Frekuensinya tergantung pada seberapa cepat komputer mampu membuat gambar. Pada komputer yang lebih lambat, Updatedisebut lebih jarang daripada yang lebih cepat. Jika Anda melakukan perhitungan berdasarkan waktu, Anda dapat menormalkannya menggunakan Time.deltaTimeyang memberi tahu Anda berapa lama sejak terakhir kali Updatedipanggil (peringatan berlaku).
Anda biasanya akan menggunakan Updateuntuk melakukan tugas yang berhubungan dengan tampilan (mis. Memperbarui elemen UI)

The FixedUpdatefungsi disebut pada interval yang tetap. Tidak peduli seberapa sering gambar di-refresh, FixedUpdateakan dipanggil 1/Time.fixedDeltaTimekali per detik.
Pada umumnya Anda akan menggunakan FixedUpdateuntuk melakukan tugas-tugas terkait gameplay (misalnya memperbarui fisika)

3Dpertanda
sumber
Apakah ini alternatif untuk mengalikan dengan waktu Time.delta? Apakah ada alasan untuk menggunakan satu atau yang lain?
Ben
@Ben mereka memiliki dua tujuan berbeda dan Anda harus menggunakan fungsi yang benar untuk apa yang Anda lakukan.
o0 '.
@ Lohoris Maaf, maksud saya apakah ada alasan untuk menggunakan FixedUpdate melalui Pembaruan dan mengalikan hal-hal dengan Time.deltaTime untuk membuat mereka bingkai independen?
Ben
@ Ya, presisi. Dalam sistem dengan rendering lambat, Updatedipanggil lebih jarang, dan simulasi Anda akan sangat menderita karenanya. Anda mungkin tidak memperhatikan sementara simulasi itu sederhana, tetapi itu akan dengan mudah pecah ketika tidak.
o0 '.
1
@Ben no: jika Anda ingin simulasi Anda lebih tepat, Anda harus mengambil banyak langkah kecil, bukan yang besar secara acak lebih besar atau lebih kecil setiap kali. Dan tidak, inti dari FixedUpdate adalah ia dipanggil berkali-kali, tanpa pertanyaan.
o0 '.
2

Dari: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate

Langkah waktu yang digunakan dalam FixedUpdate bukan variabel.

Jika gim Anda mulai ketinggalan, saat mengejar ketinggalan, Anda tidak ingin> 10 detik fisika dalam satu pembaruan, sehingga biasanya dilakukan di FixedUpdate yang disebut dengan interval tetap.

Sebagai contoh:

Update(float elapsedSeconds)
{
  Position += Velocity * 34.23423; //Windows Update is self-important
}
FixedUpdate(float elapsedSeconds)
{
  Position += Velocity * 0.0166; //60fps
}

Dimana:

Update(34.23423)

==

FixedUpdate(10.0)
FixedUpdate(10.0)
FixedUpdate(10.0)
//4.23423 + 5.76577 game-seconds later...
FixedUpdate(10.0)
Jon
sumber
Saya menyebutkan ini dalam jawaban saya, tetapi FixedUpdatetidak benar-benar dipanggil pada interval tetap. Sifat sebenarnya FixedUpdateadalah memeras beberapa siklus fisika ke dalam satu bingkai jika permainan Anda mulai melambat dan melompati siklus jika itu berjalan terlalu cepat sehingga rata-rata bekerja dengan Timestep Pembaruan Tetap. Unity tidak multi-threaded, jadi tidak ada cara untuk menjamin panggilan FixedUpdate pada interval tetap (Apa yang terjadi ketika satu FixedUpdate memakan waktu terlalu lama). Bahkan jika itu mungkin masih hampir mustahil.
Selali Adobor
Kebanyakan orang [Unity?] Tidak menyadari bahwa Render / Update / FixedUpdate semuanya dipanggil dari dalam metode panggilan balik tunggal, jadi saya membuat konsep. Terima kasih atas usaha Anda!
Jon
2

Updatedisebut secepat mungkin. Variabel 'Time.deltaTime' diatur ke jumlah waktu aktual yang berlalu sejak panggilan terakhir. Jika lag atau sesuatu yang serupa memperlambat permainan, Updatemasih akan dipanggil hanya sekali lag berakhir, dengan nilai tinggideltaTime .

FixedUpdatedisebut secara berkala. Itu tidak akan pernah dipanggil lebih sering daripada rasio yang ditentukan dalam 'Time.fixedDeltaTime'. Jika lag atau sesuatu yang serupa memperlambat permainan, FixedUpdateakan dipanggil beberapa kali berturut-turut dengan cepat untuk memungkinkan game mengejar ketinggalan. Time.deltaTimediatur sama denganTime.fixedDeltaTime sebelum FixedUpdatedijalankan, tetapi ini hanya fudge untuk membuatnya mudah untuk melakukan migrasi kode di antara keduanya.

Secara umum, Updateharus digunakan untuk perilaku interpolable dan FixedUpdateuntuk perilaku yang harus dihitung selangkah demi selangkah, atau yang tergantung pada yang melakukannya, seperti gerakan berbasis fisika. Jika Anda menulis segala jenis loop di Updatesepanjang baris untuk for(time=0;time<=deltaTime;time+=someStep)...maka Anda mungkin harus melakukannya di FixedUpdate.

Mark Green
sumber