Di mesin game Unity3D, urutan kode umum untuk mendapatkan data jarak jauh adalah ini:
WWW www = new WWW("http://remote.com/data/location/with/texture.png");
yield return www;
Apa mekanisme yang mendasarinya di sini?
Saya tahu kami menggunakan mekanisme hasil untuk memungkinkan frame berikutnya diproses, sementara unduhan sedang diselesaikan. Tetapi apa yang terjadi di bawah tenda ketika kita melakukan itu yield return www
?
Metode apa yang dipanggil (jika ada, di kelas WWW)? Apakah Unity menggunakan utas? Apakah "Unity" lapisan mendapatkan contoh www dan melakukan sesuatu?
EDIT:
- Pertanyaan ini khusus tentang internal Unity3D. Saya tidak tertarik dengan penjelasan tentang bagaimana
yield
pernyataan bekerja di C #. Sebagai gantinya, saya mencari pandangan orang dalam tentang bagaimana Unity menangani konstruksi ini, untuk memungkinkan, misalnya, ke WWW untuk mengunduh sepotong data secara didistribusikan di beberapa bingkai.
yield return
untuk operasi asinkron adalah hack. Dalam program C # "nyata", Anda akan menggunakan aTask
untuk ini. Unity mungkin tidak menggunakan mereka karena itu dibuat sebelum. Net 4.0, ketikaTask
diperkenalkan.Jawaban:
Ini adalah kata kunci C # hasilkan dalam tindakan - tidak melakukan sesuatu yang khusus dengan
www
objek, melainkan berarti sesuatu yang istimewa untuk metode yang terdapat di dalamnya. Secara khusus kata kunci ini hanya dapat digunakan dalam metode yang mengembalikanIEnumerable
(atauIEnumerator
), dan digunakan untuk menunjukkan objek apa yang akan "dikembalikan" oleh enumerator ketika MoveNext dipanggil.Ini bekerja karena kompiler mengubah seluruh metode menjadi kelas terpisah yang mengimplementasikan
IEnumerable
(atauIEnumerator
) menggunakan mesin negara - hasil akhirnya adalah bahwa tubuh metode itu sendiri tidak dieksekusi sampai seseorang menghitung melalui nilai pengembalian. Ini akan bekerja dengan jenis apa pun, sama sekali tidak ada yang istimewaWWW
, melainkan metode yang mengandung yang khusus.Lihatlah di balik layar dari kata kunci C # yield untuk beberapa wawasan lebih lanjut tentang jenis kode apa yang dihasilkan oleh kompiler C #, atau hanya bereksperimen dan periksa kodenya sendiri menggunakan sesuatu seperti IL Spy
Pembaruan: Untuk memperjelas
yield return
pernyataan, semua yang terjadi adalah bahwa enumerator dikembalikan - tidak ada satupun metode yang dieksekusi pada titik iniMoveNext
iterator untuk mendapatkan nilai pertama dalam urutan. Hal ini menyebabkan metode untuk mengeksekusi hinggayeild return
pernyataan pertama , di mana penelepon melanjutkan (dan mungkin Unity melanjutkan untuk membuat sisa frame)MoveNext
metode pada iterator sekali setiap frame berikutnya, menyebabkan metode untuk mengeksekusi kembali hinggayield return
pernyataan berikutnya sekali setiap frame, sampai akhir metode atauyield break
pernyataan tercapai (menunjukkan akhir urutan)Bit hanya khusus disini (dan dalam beberapa dari kasus lain ) adalah bahwa Unity tidak memajukan iterator tertentu frame berikutnya, bukan hanya memajukan iterator (menyebabkan metode untuk terus mengeksekusi) ketika download selesai. Meskipun tampaknya ada kelas YieldInstruction dasar yang mungkin mengandung mekanisme umum untuk pensinyalan ke Unity ketika iterator harus ditingkatkan,
WWW
kelas tersebut tampaknya tidak mewarisi dari kelas ini sehingga saya hanya dapat berasumsi bahwa ada kasus khusus untuk kelas ini di mesin Unity.Hanya untuk memperjelas -
yield
kata kunci tidak melakukan sesuatu yang istimewa untukWWW
kelas, melainkan penanganan khusus yang diberikan Unity kepada anggota enumerasi yang dikembalikan yang menyebabkan perilaku ini.Perbarui yang kedua: Adapun mekanisme yang
WWW
digunakan untuk mengunduh halaman web secara serempak mungkin menggunakan Metode HttpWebRequest.BeginGetResponse yang secara internal akan menggunakan IO yang tidak sinkron atau sebagai alternatifnya dapat menggunakan utas (baik membuat utas khusus atau dengan menggunakan utas thread).sumber
WWW
objek ketika ia dihasilkan, lihatWWW
referensi .yield
tampaknya terutama digunakan dalam Persatuan dalam konteks coroutine. Untuk membaca lebih lanjut tentang coroutine dan mengapa mereka menggunakan C #,yield
saya merekomendasikan artikel blog ini: Unity3D coroutine secara rinci . Sebagian besar penelitian dalam jawaban ini berasal dari artikel itu.Coroutine in Unity digunakan untuk merangkum tugas-tugas yang:
Contoh dari jenis tugas ini adalah merintis jalan (kembali) perhitungan atau, seperti halnya dalam pertanyaan Anda, mendapatkan data dari situs web.
Untuk menjawab pertanyaan Anda (dalam urutan yang sedikit dimodifikasi):
WWW
Kelas Unity dirancang untuk dihasilkan dari coroutine. Menurut komentar pada artikel blog yang ditautkan di atas, blok spekulatif kode (lapisan "atas") tentangYieldInstruction
s sebenarnya berisi saklar yang juga memeriksaWWW
s yang dihasilkan . Kode ini kemudian memastikan coroutine akan selesai secara otomatis ketika unduhan selesai, seperti dijelaskan dalamWWW
referensi .Dalam hal ini, untuk mengunduh data "tanpa memblokir sisa permainan": ya, kemungkinan besar. (Dan threading pasti digunakan untuk mendekompres data yang diunduh, seperti dibuktikan oleh
WWW.threadPriority
.)sumber
Sayangnya, WWW diimplementasikan secara internal sebagai kode asli, artinya kita tidak dapat melihat kode tersebut. Dari eksperimen saya bisa mengatakan itu
WWW
adalah tidak berasal dariYieldInstruction
, sehingga apa pun yang terjadi ketika Andayield
harus ditangani oleh kode-kasus khusus.Saya tidak pernah melihat perbedaan antara keduanya
dan
Saya pikir itu cara paling logis untuk mengimplementasikannya, dan kemungkinan besar itulah yang terjadi di bawah tenda. Tapi saya tidak tahu pasti.
Unity tidak memulai utas baru untuk mengunduh, setidaknya pada beberapa platform (iOS, webplayer). Atau jika ya, ini akan diatur
WWW.isDone
pada utas utama. Saya tahu ini karena kode ini:tidak bekerja
Saya tidak berpikir Anda dapat memiliki jawaban yang lebih spesifik kecuali seseorang dengan akses ke kode sumber Unity3d datang ke sini.
sumber
Karena Unity3D menggunakan C # sebagai mesin scripting mereka saya kira kata kunci hasil standar yang dibangun ke dalam C #. Pada dasarnya apa yang dimaksud adalah bahwa ia mengembalikan nilai www sehingga Anda dapat melanjutkan sementara iterasi berikutnya akan mengembalikan nilai berikutnya, dll ... Yield pada dasarnya menciptakan mesin negara dan iterator di latar belakang.
sumber
WWW
referensi . Selain itu, saya tidak yakinyield
menciptakan apa pun. Konteks iterator dibuat dengan menerapkanIEnumerable
atau menggunakannya sebagai tipe kembali. "Mesin negara" tampaknya mati juga. Tentu, ada keadaan, tetapi itu saja bukan properti yang memadai, bukan? Mungkin Anda bisa menguraikannya.