Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Game Engine Development
Gamedevelopment

Apakah Reka Bentuk Enjin Permainan Berorientasikan Data?

by
Length:LongLanguages:

Malay (Melayu) translation by Meyria (you can also view the original English article)

Anda mungkin pernah mendengar reka bentuk enjin permainan berorientasikan data, konsep yang agak baru yang mencadangkan minda yang berbeza kepada reka bentuk berorientasikan-objek yang lebih tradisional. Dalam artikel ini, saya akan menerangkan apa yang DOD kira-kira, dan mengapa sesetengah pemaju enjin permainan merasakan ia boleh menjadi tiket untuk keuntungan prestasi yang hebat.

Sedikit Sejarah

Pada tahun-tahun awal perkembangan permainan, permainan dan enjin mereka ditulis dalam bahasa sekolah lama, seperti C. Mereka adalah produk khusus, dan memerah setiap kitaran jam terakhir daripada perkakasan perlahan, pada masa itu, keutamaan yang paling utama. Dalam kebanyakan kes, terdapat hanya beberapa orang yang meretas pada kod satu tajuk tunggal, dan mereka tahu keseluruhan dasar oleh hati. Alat yang mereka gunakan telah melayani mereka dengan baik, dan C menyediakan faedah prestasi yang membolehkan mereka untuk menolak paling banyak CPU-dan kerana permainan ini masih terikat besar oleh CPU, menarik ke buffer bingkai sendiri, ini adalah perkara yang sangat penting.

Dengan kemunculan GPU yang melakukan kerja-kerja nombor-crunching pada segitiga, texel, piksel, dan sebagainya, kami telah kurang bergantung pada CPU. Pada masa yang sama, industri permainan telah menyaksikan pertumbuhan yang mantap: semakin ramai orang mahu bermain lebih banyak dan lebih banyak permainan, dan ini seterusnya membawa kepada lebih banyak pasukan yang datang bersama untuk membangunkannya.

Undang-undang Moore menunjukkan bahawa pertumbuhan perkakasan adalah eksponen, tidak linear berkenaan dengan masa: ini bermakna bahawa setiap beberapa tahun, bilangan transistor yang kita boleh muat pada satu papan tidak berubah dengan jumlah tetap-ia beregu!

Pasukan yang lebih besar memerlukan kerjasama yang lebih baik. Tidak lama kemudian, enjin permainan, dengan tahap kompleks, AI, pemusnahan, dan logik yang diperlukan memerlukan pengkod untuk lebih berdisiplin, dan senjata pilihan mereka adalah reka bentuk berorientasikan -objek.

Sebagaimana Paul Graham pernah berkata:

Di syarikat-syarikat besar, perisian cenderung ditulis oleh pasukan pengaturcara yang besar (dan sering berubah) pengaturcara biasa-biasa saja. Pengaturcaraan berorientasikan-objek mengenakan disiplin ke atas pengaturcara ini yang menghalang mana-mana daripada mereka melakukan kerosakan yang terlalu banyak.

Suka atau tidak, ini harus benar sampai tingkat tertentu — perusahaan-perusahaan yang lebih besar mulai menyebarkan game yang lebih besar dan lebih baik, dan ketika alat-alat standar muncul, para peretas yang bekerja dalam permainan menjadi bagian yang dapat ditukar dengan lebih mudah. Kebaikan penggodam tertentu menjadi kurang dan kurang penting.

Masalah Dengan Reka Bentuk Berorientasikan-Objek

Sementara desain berorientasi objek adalah konsep bagus yang membantu pengembang dalam proyek besar, seperti game, membuat beberapa lapisan abstraksi dan membuat semua orang bekerja pada lapisan target mereka, tanpa harus peduli tentang detail penerapan dari yang di bawahnya, itu pasti beri kami beberapa sakit kepala.

Kami melihat ledakan pemrograman paralel - coders memanen semua core prosesor yang tersedia untuk memberikan kecepatan komputasi yang menyala-nyala — tetapi pada saat yang sama, pemandangan permainan menjadi lebih dan lebih kompleks, dan jika kita ingin mengikuti tren itu dan tetap memberikan frame -per-detik yang para pemain kami harapkan, kami juga harus melakukannya. Dengan menggunakan semua kelajuan yang ada, kita boleh membuka pintu untuk kemungkinan yang baru: menggunakan masa CPU untuk mengurangkan jumlah data yang dihantar ke GPU sama sekali, contohnya.

Dalam pemrograman berorientasi objek, Anda menyimpan status dalam objek, yang mengharuskan Anda untuk memperkenalkan konsep seperti primitif sinkronisasi jika Anda ingin mengerjakannya dari beberapa utas. Anda memiliki satu level baru dari indirection untuk setiap panggilan fungsi virtual yang Anda buat. Dan pola akses memori yang dihasilkan oleh kode yang ditulis dengan cara yang berorientasi objek dapat menjadi mengerikan — bahkan, Mike Acton (Insomniac Games, ex-Rockstar Games) memiliki serangkaian slide besar yang dengan santai menjelaskan satu contoh.

Begitu juga, Robert Harper, seorang profesor di Carnegie Mellon University, menyatakan dengan cara ini:

Pengaturcaraan berorientasikan objek adalah [...] kedua-dua anti-modular dan anti selari dengan sifatnya yang sangat, dan oleh itu tidak sesuai untuk kurikulum CS moden.

Bercakap tentang OOP seperti ini adalah rumit, kerana OOP merangkumi spektrum sifat yang sangat besar, dan tidak semua orang bersetuju dengan maksud OOP apa. Dalam pengertian ini, saya banyak bercakap tentang OOP seperti yang dilaksanakan oleh C, kerana pada masa ini bahasa yang sangat menguasai dunia enjin permainan.

Jadi, kita tahu bahawa permainan perlu selari kerana selalu ada lebih banyak kerja yang dapat dilakukan oleh CPU (tetapi tidak perlu), dan menghabiskan kitaran menunggu GPU untuk menyelesaikan pemprosesan hanya membazir. Kami juga tahu bahawa pendekatan reka bentuk OO biasa memerlukan kami untuk memperkenalkan perbalahan kunci yang mahal, dan pada masa yang sama, boleh melanggar lokasi cache atau menyebabkan cawangan yang tidak perlu (yang boleh mahal!) Dalam keadaan yang paling tidak dijangka.

Sekiranya kita tidak mengambil kesempatan daripada banyak teras, kita terus menggunakan jumlah sumber CPU yang sama walaupun perkakasan mendapat arbitrarily lebih baik (mempunyai lebih banyak teras). Pada masa yang sama, kita boleh menolak GPU untuk hadnya kerana ia, dengan reka bentuk, selari, dan dapat mengambil apa-apa jumlah kerja serentak. Ini boleh mengganggu misi kami untuk memberikan pemain pengalaman terbaik pada perkakasan mereka, kerana kami jelas tidak menggunakannya sepenuhnya.

Ini menimbulkan persoalan: patutkah kita memikirkan kembali paradigma kita?

Masukkan: Reka Bentuk Berorientasikan Data

Beberapa penyokong metodologi ini telah menyebutnya reka bentuk berorientasikan data, tetapi sebenarnya adalah konsep umum telah diketahui lebih lama. Premis asasnya mudah: membina kod anda di sekitar struktur data, dan gambarkan apa yang anda ingin capai dari segi manipulasi struktur-struktur ini.

Kami telah mendengar perbualan seperti ini sebelum ini: Linus Torvalds, pencipta Linux dan Git, berkata dalam jawatan mailing list Git bahawa dia adalah penyokong besar untuk 'merancang kod di sekitar data, bukan sebaliknya', dan kredit ini sebagai salah satu sebab kejayaan Git. Dia pergi untuk menuntut bahawa perbezaan antara programmer yang baik dan yang buruk adalah sama ada dia bimbang tentang struktur data, atau kod itu sendiri.

Tugas itu mungkin kelihatan tidak berlawanan pada mulanya, kerana ia memerlukan anda untuk mengubah model mental anda terbalik. Tetapi fikirkan cara seperti ini: permainan, semasa berjalan, menangkap semua input pengguna, dan semua kepingan-kepingan berat (yang mana ia akan masuk akal untuk meratakan semuanya adalah falsafah objek) tidak bergantung kepada luar faktor, seperti rangkaian atau IPC. Untuk semua yang anda ketahui, permainan menggunakan peristiwa pengguna (dipindah tetikus, butang kayu bedik ditekan, dan sebagainya) dan keadaan permainan semasa, dan menyusunnya ke set data baru-contohnya, kumpulan yang dihantar ke GPU, Sampel PCM yang dihantar ke kad audio, dan keadaan permainan baru.

''Pengumpulan data'' ini boleh dipecah menjadi lebih sub-proses. Sistem animasi mengambil data utama kerangka utama dan keadaan semasa dan menghasilkan keadaan baru. Sistem zarah mengambil keadaan semasa (kedudukan partikel, halaju, dan sebagainya) dan kemajuan masa dan menghasilkan keadaan baru. Algoritma culling mengambil satu set kandang kandung kandung dan menghasilkan satu set yang lebih kecil yang boleh digunakan. Hampir segala-galanya dalam enjin permainan boleh dianggap sebagai memanipulasi sebahagian data untuk menghasilkan data lain.

Pemproses suka daerah rujukan dan penggunaan cache. Oleh itu, dalam reka bentuk yang berorientasikan data, kita cenderung, jika boleh, mengatur segala sesuatu di dalam susunan yang besar dan homogen, dan, di mana juga mungkin, jalankan algoritma kekerasan cache yang koheren yang baik, sebagai pengganti yang berpotensi yang merana (yang mempunyai kos Big O yang lebih baik, tetapi gagal untuk merangkumi keterbatasan seni bina perkakasan yang berfungsi pada).

Apabila dilakukan setiap bingkai (atau berbilang kali setiap bingkai), ini berpotensi memberikan ganjaran prestasi yang besar. Contohnya, orang-orang di Scalyr melaporkan mencari fail log pada 20GB / saat dengan menggunakan senario linear kasar yang dibuat dengan hati-hati.

Apabila kita memproses objek, kita perlu memikirkannya sebagai 'kotak hitam' dan memanggil kaedah mereka, yang seterusnya mengakses data dan mendapatkan apa yang kita mahu (atau membuat perubahan yang kita mahu). Ini hebat untuk bekerja untuk kelayakan, tetapi tidak mengetahui bagaimana data kami dibentangkan boleh menjejaskan prestasi.

Contoh

Reka bentuk berorientasikan data telah memikirkan semua tentang data, jadi mari kita melakukan sesuatu yang juga sedikit berbeza dari yang biasanya kita lakukan. Pertimbangkan sekeping kod ini:

Walaupun mudah dipermudahkan, corak umum ini adalah yang sering dilihat dalam enjin permainan berorientasikan- objek. Tetapi tunggu-jika banyak penyajian tidak dapat dilihat, kita mengalami banyak kesalahan misal cawangan yang menyebabkan prosesor membuang beberapa arahan yang telah dilaksanakan untuk mengharapkan cawangan tertentu diambil.

Untuk adegan kecil, ini jelas bukan masalah. Tetapi berapa kali anda melakukan perkara yang khusus ini, bukan hanya apabila beratur ditugaskan, tetapi apabila melewati lampu tempat kejadian, perpaduan peta bayang, zon, atau sejenisnya? Bagaimana pula dengan kemas kini AI atau animasi? Majukan semua yang anda lakukan sepanjang tempat kejadian, lihat berapa banyak pusingan jam yang anda buang, hitungkan berapa kali pemproses anda ada untuk menyampaikan semua kumpulan GPU untuk irama 120FPS yang mantap, dan anda dapat melihat bahawa perkara-perkara ini boleh mencecah jumlah yang besar.

Sebagai contoh, seorang penggodam yang bekerja di aplikasi web bahkan menganggap pengoptimuman mikro kecil itu, tetapi kita tahu bahawa permainan adalah sistem masa nyata di mana kekangan sumber sangat ketat, jadi pertimbangan ini tidak salah bagi kami.

Untuk mengelakkan perkara ini daripada berlaku, mari kita fikirkannya dengan cara lain: bagaimana jika kita menyimpan senarai bahan yang boleh dilihat dalam enjin? Pasti, kami akan mengorbankan sintaks kemas myRenerable-> hide () dan melanggar beberapa prinsip OOP, tetapi kami kemudiannya boleh melakukan ini:

Hooray! Tiada muflis cawangan, dan menganggap mVisibleRenderables adalah std :: vektor yang bagus (iaitu array yang bersebelahan), kita juga boleh menulis semula ini sebagai panggilan memcpy yang cepat (dengan beberapa kemas kini tambahan kepada struktur data kita, mungkin).

Sekarang, anda boleh memanggil saya dengan kesilapan semata-mata contoh-contoh kod ini dan anda akan betul: ini banyak dipermudahkan. Tetapi untuk jujur, saya tidak pernah tercalar permukaannya lagi. Berfikir mengenai struktur data dan hubungan mereka membuka kita kepada banyak kemungkinan yang kita tidak fikirkan sebelum ini. Mari lihat beberapa daripada mereka seterusnya.

Penyelarasan dan Vektor

Sekiranya kita mempunyai fungsi mudah dan jelas yang beroperasi pada ketulan data yang besar sebagai blok asas untuk pemprosesan kami, mudah untuk menanam empat, atau lapan, atau 16 benang pekerja dan memberi setiap satu daripada sekeping data untuk memastikan semua CPU teras sibuk. Tidak ada mutexes, atomics atau pertikaian kunci, dan sebaik sahaja anda memerlukan data, anda hanya perlu menyertai semua benang dan menunggu mereka selesai. Sekiranya anda perlu menyusun data selari (tugas yang sangat kerap apabila menyediakan barangan untuk dihantar ke GPU), anda perlu memikirkannya dari perspektif yang berbeza-slaid ini mungkin membantu.

Sebagai bonus tambahan, dalam satu thread anda boleh menggunakan arahan vektor SIMD (seperti SSE / SSE2 / SSE3) untuk mencapai peningkatan kelajuan tambahan. Kadang-kadang, anda boleh melakukan ini hanya dengan meletakkan data anda dengan cara yang berbeza, seperti meletakkan array vektor dalam bentuk struktur-of-array (SoA) (seperti XXX ... YYY ... ZZZ ...) dan bukannya konvensional array-of-struktur (AoS; yang akan menjadi XYZXYZXYZ ...). Saya hampir tidak menggaru permukaan di sini; anda boleh mendapatkan lebih banyak maklumat dalam bahagian Bacaan Lanjut di bawah.

Apabila algoritma kami berurusan dengan data secara langsung, ia menjadi remeh untuk menyamakannya, dan kami juga boleh mengelakkan kekurangan kelajuan.

Unit Ujian Anda Tidak Tahu Kemungkinan

Mempunyai fungsi mudah tanpa kesan luaran menjadikannya mudah untuk ujian unit. Ini boleh menjadi sangat baik dalam bentuk ujian regresi untuk algoritma yang anda ingin bertukar masuk dan keluar dengan mudah.

Sebagai contoh, anda boleh membina suite ujian untuk tingkah laku algoritma yang membuang, menubuhkan persekitaran yang dirancang, dan mengukur dengan tepat bagaimana ia berfungsi. Apabila anda membuat algoritma pemalsuan yang baru, anda menjalankan ujian yang sama sekali lagi tanpa sebarang perubahan. Anda mengukur prestasi dan ketepatan, supaya anda boleh membuat penilaian di hujung jari anda.

Apabila anda mendapatkan lebih banyak pendekatan pendekatan berorientasikan data, anda akan mendapati lebih mudah dan lebih mudah untuk menguji aspek enjin permainan anda.

Menggabungkan Kelas dan Objek Dengan Data Monolitik

Reka bentuk berorientasikan data tidak semestinya menentang pengaturcaraan berorientasikan objek, hanya beberapa ideanya. Akibatnya, anda boleh menggunakan idea-idea yang rapi daripada reka bentuk berorientasikan data dan masih mendapat sebahagian besar abstraksi dan model mental yang anda gunakan.

Lihatlah, sebagai contoh, pada kerja di OGRE versi 2.0: Matias Goldberg, dalang di sebalik usaha itu, memilih untuk menyimpan data dalam array besar, homogen, dan mempunyai fungsi yang meleleh ke atas keseluruhan susunan berbanding dengan hanya satu datum , untuk mempercepatkan Ogre. Menurut penanda aras (yang dia akui adalah sangat tidak adil, tetapi kelebihan prestasi diukur tidak boleh hanya kerana itu) ia berfungsi sekarang tiga kali lebih cepat. Bukan hanya itu-dia mengekalkan banyak abstraksi lama, biasa, jadi API jauh dari penulisan semula lengkap.

Adakah Ia Praktikal?

Terdapat banyak bukti bahawa enjin permainan dengan cara ini boleh dan akan dibangunkan.

Blog pembangunan Molecule Engine mempunyai siri bernama Adventures dalam Rancangan Berorientasikan Data, dan mengandungi banyak nasihat yang bermanfaat mengenai di mana DOD digunakan dengan hasil yang hebat.

DICE nampaknya berminat dalam reka bentuk berorientasikan data, kerana mereka telah menggunakannya dalam sistem pemusnah Engine Frostbite (dan mendapat ketara, kelajuan-up juga!). Sesetengah slaid lain dari mereka juga termasuk menggunakan reka bentuk berorientasikan data dalam subsistem AI-patut dilihat juga.

Selain itu, pemaju seperti Mike Acton yang dinyatakan di atas seolah-olah merangkul konsep itu. Terdapat beberapa tanda aras yang membuktikan bahawa ia mendapat banyak prestasi, tetapi saya tidak melihat banyak aktiviti di hadapan reka bentuk berorientasikan data dalam beberapa waktu. Ia sememangnya boleh menjadi satu bentuk, tetapi premis utamanya kelihatan sangat logik. Terdapat pasti banyak inersia dalam perniagaan ini (dan sebarang perniagaan pembangunan perisian lain, untuk perkara itu) jadi ini mungkin menghalang pengangkatan falsafah besar-besaran. Atau mungkin ia bukan idea yang hebat seperti mana. Apa pendapat kamu? Komen adalah sangat dialu alukan!

Bacaan lanjut

  1. Reka Bentuk Berorientasikan Data (Atau Kenapa Anda Boleh Menembak Diri Anda di Kaki Dengan OOP)
  2. Pengenalan Reka Berorientasikan Data [DICE]
  3. Perbincangan yang agak baik pada Stack Overflow
  4. Buku dalam talian oleh Richard Fabian menjelaskan banyak konsep
  5. Penanda aras yang menunjukkan sisi lain dari cerita itu, keputusan yang seolah-olah bersifat intuitif
  6. Kajian Mike Acton tentang OgreNode.cpp, mendedahkan beberapa masalah pembangunan enjin permainan OOP biasa

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.