Panggilan Fungsi Per-Bingkai versus Perpesanan Berbasis Acara dalam Desain Game

11

Desain game tradisional , seperti yang saya tahu, menggunakan polimorfisme dan fungsi virtual untuk memperbarui status objek game. Dengan kata lain, rangkaian fungsi virtual yang sama disebut dengan interval reguler (ex: per-frame) pada setiap objek dalam game.

Baru-baru ini, saya menemukan, bahwa ada sistem pesan berbasis event lain yang tersedia untuk memperbarui status objek game. Di sini, objek biasanya tidak diperbarui berdasarkan per-frame. Alih-alih, sistem pesan acara yang sangat efisien dibuat, dan objek permainan diperbarui hanya setelah menerima pesan acara yang valid.

Arsitektur Game Driven Event dijelaskan dengan baik di: Game Coding Lengkap oleh Mike McShaffry .

Bisakah saya meminta bantuan dengan pertanyaan-pertanyaan berikut:

  • Apa kelebihan dan kekurangan dari kedua pendekatan tersebut?
  • Di mana yang lebih baik dari yang lain?
  • Apakah desain game yang didorong Event universal dan lebih baik di semua bidang? Apakah karena itu direkomendasikan untuk penggunaan bahkan di platform mombile?
  • Mana yang lebih efisien dan mana yang lebih sulit untuk dikembangkan?

Untuk memperjelas, pertanyaan saya bukan tentang menghapus polimorfisme sepenuhnya dari desain game. Saya hanya ingin memahami perbedaan dan manfaat dari menggunakan pesan yang digerakkan oleh acara vs panggilan biasa (per-frame) ke fungsi virtual untuk memperbarui status permainan.


Contoh: Pertanyaan ini menyebabkan sedikit kontroversi di sini, jadi izinkan saya menawarkan Anda contoh: Menurut MVC, mesin permainan dibagi menjadi tiga bagian utama:

  1. Lapisan Aplikasi (Perangkat Keras dan komunikasi OS)
  2. Logika Game
  3. Tampilan Game

Dalam gim balap, Game View bertanggung jawab untuk merender layar secepat mungkin, setidaknya 30fps. Game View juga mendengarkan input pemain. Sekarang ini terjadi:

  • Pemain menekan pedal bahan bakar hingga 80%
  • GameView membuat pesan "Pedal 2 Bahan Bakar Mobil Ditekan hingga 80%" dan mengirimkannya ke Game Logic.
  • Game Logic mendapatkan pesan, mengevaluasi, menghitung posisi dan perilaku mobil baru dan membuat pesan berikut untuk GameView: "Draw Car 2 Fuel Pedal Pressed 80%", "Car 2 Sound Acceleration", "Car 2 Coordinates X, Y" .. .
  • GameView menerima pesan dan memprosesnya sesuai
Bunkai.Satori
sumber
dimana kamu menemukan beberapa tautan atau referensi? Saya tidak tahu pendekatan ini (tetapi saya tahu pola desain yang sangat umum pada umumnya, dan saya menyarankan penggunaan prinsip orientasi objek yang baik secara umum), tetapi saya pikir yang berbasis event lebih baik .. pikirkan evolusi dalam sistem jaringan: dari polling untuk panggilan asynchronous .. itu dioptimalkan dalam perhitungan dan di tingkat abstraksi
nkint
Hai Nkint, terima kasih atas komentar Anda. Saya pada dasarnya ingin membandingkan komunikasi event vs panggilan ke fungsi virtual. Saya akan sedikit memodifikasi pertanyaan saya. Btw, lihat tautan ini yang berisi pola permainan: gameprogrammingpatterns.com .
Bunkai.Satori
5
Mungkin saya bodoh, tetapi bagaimana Anda akan membuat sistem pengiriman pesan berfungsi tanpa menggunakan polimorfisme? Tidakkah Anda akan membutuhkan semacam kelas dasar (abstrak atau lainnya) untuk mendefinisikan antarmuka penerima acara Anda? (Sunting: dengan asumsi Anda tidak bekerja dalam bahasa dengan refleksi yang tepat.)
Tetrad
2
Juga, efisiensi akan sangat terkait dengan detail implementasi. Saya tidak berpikir "mana yang lebih efisien" adalah pertanyaan yang dapat dijawab dalam bentuk saat ini.
Tetrad
1
Objek game perlu dicentang. Objek game perlu berkomunikasi satu sama lain. Kedua hal itu perlu terjadi. Yang pertama tidak Anda lakukan dengan olahpesan karena berlebihan (Anda mungkin memiliki daftar semua objek di suatu tempat, panggil saja update). Yang kedua bisa Anda lakukan dengan olahpesan karena berbagai alasan.
Tetrad

Jawaban:

8

Saya sangat percaya pada kebutuhan menjadi ibu dari penemuan. Saya tidak suka kode apa pun kecuali kebutuhannya jelas dan terdefinisi dengan baik. Saya pikir jika Anda memulai proyek Anda dengan mengatur sistem pesan acara, Anda salah melakukannya. Saya percaya bahwa hanya sekali Anda telah membuat dan menguji infrastruktur Anda dan memiliki semua bagian untuk proyek Anda yang terdefinisi dengan baik, modul kerja harus Anda fokuskan pada bagaimana Anda akan menghubungkan modul-modul ini satu sama lain. Mencoba merancang sistem pesan acara sebelum Anda memahami bentuk dan kebutuhan setiap modul tidak sesuai.

Apa kelebihan dan kekurangan dari kedua pendekatan tersebut?

Saya pikir beberapa orang akan berpendapat bahwa ada sistem pesan yang baik di luar sana yang siap diinstal dan digunakan. Mungkin ini benar. Tentu saja kinerja solusi membangun-khusus yang dirancang khusus untuk kebutuhan Anda akan lebih besar daripada bus pesan tujuan umum. Pertanyaan besarnya adalah - berapa banyak waktu yang Anda habiskan untuk membangun sistem pesan daripada menggunakan sesuatu yang sudah dibangun. Jelas, jika Anda dapat menemukan semacam sistem acara dengan set fitur yang Anda butuhkan, maka itu adalah keputusan yang cukup mudah. Inilah sebabnya saya memastikan bahwa saya mengerti apa yang saya butuhkan sebelum saya membuat keputusan itu.

Di mana yang lebih baik dari yang lain?

Kita dapat berbicara tentang memori dan sumber daya di sini. Jika Anda mengembangkan perangkat keras apa pun dengan sumber daya terbatas, tentu saja merupakan masalah untuk menggunakan sistem acara yang akan memotongnya secara signifikan. Tapi sungguh, saya pikir masalahnya adalah apa yang Anda butuhkan, yang seperti yang saya sebutkan sudah merupakan sesuatu yang Anda tidak tahu sampai Anda melihat seperti apa semua potongan itu. Jika Anda memiliki cukup pengalaman dalam membangun sistem ini yang Anda tahu sebelumnya persis seperti apa semua bagiannya, maka Anda dapat menjawab pertanyaan ini sebelumnya. Saya kira Anda tidak memiliki pengalaman ini, karena Anda tidak akan menanyakan pertanyaan ini jika Anda melakukannya.

Apakah desain game yang didorong Event universal dan lebih baik di semua bidang? Apakah karena itu direkomendasikan untuk penggunaan bahkan di platform seluler?

Universal dan lebih baik di semua bidang? Pernyataan selimut yang cantik seperti itu mudah ditolak. Apa pun yang menambahkan overhead harus membawa bagiannya dari beban kerja. Jika Anda tidak cukup menggunakan acara untuk menjamin overhead desain, maka itu desain yang salah.

Mana yang lebih efisien dan mana yang lebih sulit untuk dikembangkan?

Efisiensi tergantung pada bagaimana penerapannya. Saya pikir desain tradisional yang berkembang dengan baik akan mengalahkan sistem berbasis acara setiap hari dalam seminggu. Ini karena komunikasi antar potong dapat dikelola secara mikro dan dibuat sangat efisien. Tentu saja, ini juga membuatnya lebih sulit untuk dirancang dari sudut pandang pengalaman dan waktu yang dibutuhkan untuk menyelesaikannya dan membuatnya lebih efisien. Di sisi lain, jika Anda kurang pengalaman ini atau tidak punya waktu untuk mengembangkan aplikasi dengan baik, maka menggunakan desain berbasis acara yang sesuai dengan kebutuhan Anda akan lebih efisien. Jika Anda memiliki kebutuhan acara khusus yang tidak mudah masuk ke dalam struktur berbasis acara, ini bisa membuat struktur berbasis acara sangat sulit untuk dirancang - terutama untuk menjaga agar desain tetap efisien.

Erick Robertson
sumber
Hai Eric, terima kasih atas pendapat terperinci Anda tentang pertanyaan saya. Saat saya membaca tanggapan Anda dan orang lain, menerapkan pesan acara mungkin tidak menyebabkan keajaiban dalam peningkatan kinerja game secara keseluruhan. Sebaliknya itu akan menyulitkan banyak hal. Saya ingin melihat beberapa jawaban lagi, sebelum menutup pertanyaan ini. Ketika seluruh buku membahas topik ini, sepertinya ide yang bagus untuk dipertimbangkan. Saya tidak begitu yakin, apakah keputusan untuk menggunakan atau tidak menggunakan pesan dapat dibuat di tengah-tengah proyek. Jika pesan acara digunakan, saya akan mengatakan, desain objek keseluruhan harus disesuaikan juga.
Bunkai.Satori
Saya tidak setuju. Jika keseluruhan desain objek dienkapsulasi dengan baik, itu harus cukup fleksibel untuk digunakan dalam segala jenis kerangka kerja. Saya telah dapat menukar metode komunikasi dalam proyek-proyek besar dengan pekerjaan yang sangat sedikit karena masing-masing bagian dikemas dengan baik.
Erick Robertson
7

Saya pikir Anda membandingkan apel dan jeruk di sini. Polimorfisme tidak digantikan oleh olah pesan sama sekali. Anda mungkin ingin acara / pesan untuk menghubungkan komponen yang digabungkan secara longgar. Misalnya. untuk mengirim pesan dari suatu entitas ketika tabrakan terjadi, untuk memperbarui skor pemain atau mungkin untuk memicu efek suara. Sehingga masing-masing kelas tidak mengenal kelas lain dan hanya mengirim dan / atau menangani pesan.

Tetapi game Anda kemungkinan besar akan memiliki loop pembaruan di suatu tempat dan karena Anda memiliki loop pembaruan itu, itu dapat dengan mudah digunakan untuk memperbarui semua entitas game yang perlu diperbarui setiap frame juga. Ini tidak mencegah Anda dari menggunakan olahpesan ...

Jika Anda memiliki semacam struktur tempat Anda menambahkan / menghapus entitas game, Anda dapat memasukkannya ke dalam loop pembaruan Anda alih-alih mengirimkan pesan pembaruan kepada mereka setiap frame. Jadi mengapa tidak memanggil pembaruan pada entitas game Anda secara langsung saat Anda menggunakan pesan untuk menghubungkan berbagai sub-sistem game Anda? Saya juga suka konsep Sinyal / Slot ( lihat contoh qt ) untuk sistem seperti acara.

Intinya: Tidak ada pendekatan yang lebih baik, juga tidak eksklusif.

bummzack
sumber
Hai, Bummzack. Akhirnya, jawaban pertama tiba. Terima kasih untuk itu :-) Ketika saya menyebutkan Arsitektur Event Driven, saya maksudkan sistem MVC dengan tiga lapisan utama: Appliaction, GameView, GameLogic. Semua komunikasi antara trhee ini akan dilakukan melalui olahpesan. Ini sangat berbeda dengan sistem tradisional dengan loop pembaruan. Setiap sistem memiliki arsitektur yang berbeda, beberapa kelebihan dan kekurangan, dan mereka memiliki biaya kinerja yang berbeda. Karena itu saya percaya, seseorang akan sedikit lebih baik di beberapa daerah. Setelah analisis yang baik, kita harus bisa menyimpulkan mana yang lebih baik.
Bunkai.Satori
3
Saya gagal melihat mengapa ini berbeda? Anda akan memerlukan loop pembaruan di suatu tempat dan itu mungkin akan memperbarui Controller jika Anda ingin tetap menggunakan MVC. Kemudian controller dapat mengirimkan pesan kepada model dan tampilan .. tetapi karena controller biasanya mengetahui tampilan dan model, ia juga dapat memperbaruinya secara langsung. Tetapi ini tidak menggantikan polimorfisme apa pun. Pertanyaan dan asumsi Anda terdengar sangat teoretis .. mungkin mendukungnya dengan beberapa contoh kode atau beberapa referensi?
bummzack
Buku yang disebutkan di atas, Game Coding Complete, merekomendasikan pengiriman pesan acara melalui panggilan langsung ke metode virtual. Meskipun, sistem pesan terlihat lebih kompleks, keuntungannya adalah, bahwa setiap objek game tidak perlu memeriksa dunia game. Dunia game diperiksa oleh logika game hanya sekali, dan kemudian hanya objek-objek yang dialamatkan yang seharusnya mengubah status mereka. Ini satu perbedaan, dan bisa berarti penghematan biaya. Jika Anda memutuskan bahwa objek permainan Anda akan berkomunikasi melalui pesan, mereka tidak akan disebut masing-masing bingkai - oleh karena itu kedua pendekatan tersebut saling eksklusif.
Bunkai.Satori
1
Dipilih untuk jawaban yang mencerminkan komentar Tetrad di bawah pertanyaan awal. @ Bunkai.Satori 'Dunia permainan hanya diperiksa sekali' adalah loop pembaruan, semua yang perlu diperbarui mendapatkannya. Pesan Acara dimaksudkan untuk menjadi yang jarang dilakukan tetapi masih hal-hal penting dalam mesin (PlayerDied, MonsterDied, dll) yang memeriksa setiap frame dalam pembaruan () loop akan sia-sia, tetapi mereka kemungkinan besar dihasilkan oleh Perbarui () loop itu sendiri.
James
1
Jika Anda memiliki Edisi Kedua, lihat bab berjudul Mengontrol Loop Utama. Itu harus dinamai hal yang sama di edisi ke-3. Itu benar-benar harus menjawab pertanyaan Anda.
Ray Dey
4

Ini dimulai sebagai komentar untuk jawaban bummzack, tetapi panjang.

Kecuali jika Anda benar-benar menjadikannya tidak sinkron (mengirim acara pada utas baru), objek Anda masih mendapatkan memo secara sinkron. Dengan asumsi dispatcher acara Anda menggunakan tabel hash dasar dengan daftar yang ditautkan dalam sel, urutannya akan menjadi urutan di mana objek diiklankan ke sel itu.

Lebih lanjut, kecuali Anda memutuskan untuk menggunakan pointer fungsi karena suatu alasan, Anda masih menggunakan panggilan fungsi virtual karena setiap objek yang menerima pesan harus mengimplementasikan IEventListener (atau apa pun namanya). Acara adalah abstraksi tingkat tinggi yang Anda buat menggunakan polimorfisme.

Gunakan peristiwa di mana Anda harus memanggil daftar metode pencucian untuk berbagai kejadian dalam gim untuk menyinkronkan berbagai sistem dalam gim atau di mana berbagai objek dan reaksi sistem sehingga kejadian tersebut tidak dapat didefinisikan dengan jelas atau Anda inginkan untuk menambahkan lebih banyak reaksi terhadap kejadian tersebut di masa depan.

Mereka adalah alat yang hebat, tetapi seperti kata bummzack, jangan menganggap bahwa polimorfisme dan peristiwa memecahkan masalah yang sama.

michael.bartnett
sumber
Hai Bearcdp, terima kasih atas balasan Anda. Masuk akal bagi saya. Ada satu hal dalam benak saya, yaitu memilih pesan acara: katakanlah, ada 200 oject di tempat kejadian. Jika Anda menggunakan panggilan fungsi per-frame pada semua objek, Anda harus memeriksa semua 200 objek untuk collision setiap frame (contoh; tentu saja interval panggilan dapat dikelola.) Dengan olahpesan acara, gameworld diperiksa hanya sekali. Jika ada 5 tabrakan, hanya 5 objek yang diberi tahu oleh pesan tentang peristiwa tabrakan, alih-alih 200 uji deteksi collison dengan panggilan per-bingkai. Apa pendapat Anda?
Bunkai.Satori
2
periksa gameworld ?? apa artinya? Itu harus berarti menjalankan 200 cek yang sama untuk mengisolasi 5 yang perlu dikirimi pesan. Dengan konsep fungsi virtual, gameworld hanya diperiksa sekali juga (fungsi masing-masing objek pada gilirannya), dan kemudian pindah ke hanya 5 yang perlu diubah negara ... tanpa overhead dari sistem pesan.
Steve H
1
Dengarkan Steve H, dunia tidak bertabrakan dengan sendirinya. Saya terutama menggunakan acara untuk kejadian tingkat tinggi, seperti PlayerJump, EnemyHit. Untuk menangani efisiensi pemeriksaan tabrakan, Anda perlu memilih struktur data untuk mengatur lokasi fisik objek dalam game Anda sehingga Anda dapat memprioritaskan objek mana yang perlu dan tidak perlu diperiksa untuk tabrakan. Setelah Anda menentukan semua pasangan objek yang bertabrakan, maka Anda dapat mengirim acara dengan data tumbukan yang relevan (dua objek, kecepatan / posisi / data normals, dll.).
michael.bartnett
Halo Steve dan Beardcp, terima kasih atas komentar Anda. Apa yang Anda tulis masuk akal. Sepertinya ada banyak kemungkinan implementasi sistem pesan acara. Mungkin ada penggantian murni dari konsep fungsi virtual per-frame, seperti yang dikatakan buku di atas. Namun, sistem olahpesan dapat berdampingan dengan konsep fungsi virtual per-bingkai juga, seperti yang Anda katakan.
Bunkai.Satori
Mengapa Anda mengatakan "untuk beberapa alasan" sehubungan dengan pointer fungsi? Itu cukup banyak bagaimana saya menerapkan sistem acara saat saya menulis satu dari awal (saya bekerja dalam bahasa yang memiliki fungsi kelas satu tapi itu ide yang sama; meneruskan fungsi ke objek hub acara dan objek yang memetakan fungsi pendengar ke peristiwa) jadi saya bertanya-tanya apakah ada kerugian untuk pendekatan itu.
jhocking
2

Saya akan mengatakan bahwa memilih satu atau yang lain cukup salah. Beberapa objek perlu memanggil setiap frame - beberapa tidak. Jika Anda memiliki objek yang ingin Anda render, Anda harus membuat panggilan render ke setiap frame. Acara tidak dapat membuat perubahan ini. Hal yang sama berlaku untuk objek fisika berbasis waktu apa pun - Anda harus memanggil mereka setiap bingkai.

Namun, saya tidak membuat panggilan setiap frame ke objek manajemen objek saya, atau objek input pengguna saya, atau yang seperti itu. Panggilan virtual massal ke setiap objek pada bingkai adalah ide yang buruk.

Desain yang digunakan untuk objek tertentu harus didasarkan pada kebutuhan objek tersebut, dan tidak didasarkan pada beberapa ideologi untuk sistem secara keseluruhan.

Diedit agar lebih jelas pada kalimat pertama saya.

DeadMG
sumber
Halo DeadMG, izinkan saya menjelaskan: Dalam kasus yang disebutkan di atas, desain dibagi menjadi tiga bagian utama: Lapisan appliaction (akses perangkat keras), Game Logic, Game View. Apa yang dihasilkan per basis frame adalah Tampilan Game. Namun, ketika Game View merekam input pengguna (mis. Pedal rem ditekan dalam mengejar game) mengirimkan pesan "Car 2 Brake Pressed" ke Game Logic untuk diproses. Game Logic mengevaluasi tindakan ini, menghitung perilaku mobil, dan mengirim pesan ke Game View: "Car 2 Block Tyres", "Car 2 Move to X, Y". Dengan cara ini tidak perlu memeriksa per frame, jika rem ditekan pada setiap mobil.
Bunkai.Satori
@ Bangunk: Jadi Anda memiliki beberapa desain yang dikendalikan oleh acara dan beberapa desain yang disebut masing-masing bingkai. Cukup banyak setuju dengan jawaban saya.
DeadMG
Saya senang menemukan pengertian dengan Anda, karena pertanyaan ini agak kontroversial di sini hari ini :-)
Bunkai.Satori