Pembaruan objek, internal vs eksternal?


8

Judulnya agak membingungkan, tetapi saya tidak bisa memikirkan bagaimana menjelaskan pertanyaan saya dalam frasa singkat. Jadi begini:

Setiap kali saya menulis mesin permainan, apakah itu fisika / dll berbasis, saya selalu sampai pada titik di mana saya tidak yakin bagaimana saya harus mengatur sesuatu. Haruskah entitas di dunia menangani sendiri, atau haruskah ada sistem global yang mengelolanya?

Ini contoh mudahnya: Memindahkan barang. Haruskah setiap objek melihat dunia di sekitarnya (periksa tabrakan) dan bergerak berdasarkan itu.

[perhatikan, ini adalah game berbasis ubin tempat objek bergerak per ubin, jadi saya tidak menggunakan fisika untuk berpindah dari ubin ke ubin]

public class Actor : GameObject
    {
        private void MoveTo(Vector2 location)
        {
            if (world.getTile(location) != solid && world.objAtTile(location) == null)
            {
                Tweener.addTween(this, location);
            }
          }
        }

Atau haruskah pergerakan setiap benda ditangani di dunia, di mana dunia memeriksa semuanya?

public class Actor : GameObject
    {
        private void MoveTo(Vector2 location)
        {
            world.moveTo(location);
          }
        }

public class World
{

    public void moveObject(GameObject obj, Vector2 location)
    {
      //called from object

      if (getTile(location) != solid && objAtTile(location) == null)
         {
                Tweener.addTween(obj, location);
         }
    }
}

Saya kira tidak terlalu penting untuk contoh ini, tetapi saya bisa melihat diri saya mendapat masalah nanti. Terima kasih sebelumnya.


1
Lebih banyak pertanyaan, harus Actortahu worldsama sekali?
deceleratedcaviar

1
Saya pikir Anda menggabungkan Objek dengan Komponen dan itu membingungkan masalah siapa yang melakukan apa. Ini mungkin masalah semantik karena Komponen adalah istilah yang kelebihan beban. Saya pikir jika Anda mengklarifikasi apa Obyek itu, apa yang Anda maksud dengan Komponen dan bagaimana Anda mengatur mesin kecil yang benar-benar menyelesaikan pekerjaan maka Anda dapat menjawab pertanyaan Anda sendiri.
Patrick Hughes

1
Saya harus setuju dengan orang lain bahwa Anda bertanya apakah objek game bergerak sendiri atau apakah dunia memindahkan objek game. Kode di atas tidak membuat saya percaya bahwa Anda benar-benar memaksudkan sistem tipe komponen dan mungkin menyesatkan dalam judul pertanyaan Anda.
James

Saya memang menggunakan beberapa istilah yang menyesatkan sekarang karena kalian menyebutkannya. Akan menyesuaikannya sekarang! Sunting: Lihat itu sudah diubah, terima kasih!
omgnoseat

@daniel Aktor jelas perlu memiliki pengetahuan tentang dunia di sekitar mereka agar dapat bergerak secara efektif, meskipun saya biasanya akan merancang sekitar wadah yang merangkum keduanya tetapi tidak ada yang tahu. misalnya. Dunia mengandung Aktor dan Level; Aktor tahu tentang Level (atau lebih tepatnya diberitahu tentang Level saat dibutuhkan, tetapi bukan referensi permanen) tetapi tidak tentang Dunia.
jhocking

Jawaban:


2

Saya melihat contoh Anda di Jawa, tetapi tag Anda tidak menentukan bahasa apa pun. Dalam C ++, jawabannya adalah tidak - Anda tidak boleh menggunakan fungsi anggota untuk ini!

void move_to(actor *a, world *w, vec2 location);

4
Harus mengatakan penggemar buku yang ditulis oleh penulis artikel. Namun alasan dari artikel ini adalah, sejauh yang saya tahu, teori yang bagus tetapi bukan kode praktis. Dengan memindahkan metode seperti ini keluar dari objek yang berkaitan dengan Anda menambahkan lebih banyak lokasi untuk mencari fungsionalitas yang berkaitan dengannya yang hanya menyebabkan kebingungan dan tingkat pemeliharaan yang lebih tinggi diperlukan. Hanya pandangan saya tentang itu, jadi tidak ada + atau -. Hanya dua sen.
James

1
Juga, harus mengatakan bahwa itu tampak seperti C # dengan warisan menggunakan: ClassName alih-alih meluas ClassName.
James

Ini kode semu yang didasarkan pada C #, tetapi itu seharusnya tidak relevan dengan pertanyaan saya :)
omgnoseat

1
@omgnoseat: Ini relevan karena saran tidak mungkin dalam bahasa tanpa fungsi kosong, dan kegunaannya dikurangi dalam bahasa apa pun tanpa ADL. Arsitektur yang baik tidak terlepas dari pilihan bahasa.

2
@ James: Tidak ada yang non-OO tentang fungsi telanjang, jika fungsi itu sendiri memanggil metode yang mengikuti prinsip-prinsip desain OO. Itulah poin dari artikel ini. (OO juga tidak identik dengan desain yang baik. Jika desain yang jelas atau sederhana mengharuskan Anda untuk tidak menggunakan OO, parit OO, bukan desain.)

1

Tidak ada jawaban sederhana.

Seperti kebanyakan hal dalam pemrograman, ini merupakan trade off. Memberi lebih banyak daya ke objek individual membuatnya lebih besar - dan karenanya lebih lambat - tetapi membuat mesin lebih mudah dipahami dan diperluas. Memiliki kelas mega yang dapat menangani semuanya bersama mungkin lebih cepat, tetapi dengan biaya memiliki kelas mega; yaitu, umumnya dianggap bentuk buruk untuk membuat kelas supermasif.

Saya telah membaca beberapa artikel tentang komponen dan desain berbasis data, di mana Anda memiliki kelas tunggal yang mewakili semua objek dari jenis tertentu, menyimpan data mereka dalam daftar, dan hanya membagikan indeks untuk mendapatkan properti dari objek individual. Meskipun saya bisa melihat ini sebagai jenis arsitektur yang layak, saya merasa itu agak kacau dengan seluruh titik orientasi objek, yang juga mendapat banyak kritik.

Saya pribadi merekomendasikan memberi lebih banyak kekuatan ke objek. Itu lebih masuk akal dalam bahasa berorientasi objek, dan (saya akan membayangkan) lebih mudah untuk memahami dan memelihara dari waktu ke waktu.


Anda agak meremehkan hal-hal dengan mengatakan bahwa gaya desain komponen dan data yang Anda gambarkan "sekrup dengan seluruh titik OO" - itu bukan OO sama sekali. Setidaknya seperti yang dijelaskan dalam "Sistem Entitas adalah masa depan pengembangan MMOG" (terkait dalam jawaban pek), sistem entitas adalah paradigma pemrograman yang sama sekali berbeda dan jika Anda menemukan diri Anda mencoba membuat komponen atau entitas OO Anda di luar kenyamanan pengemasan yang sederhana, Anda ulang Melakukannya Salah.
Dave Sherohman

6
Mereka sangat berorientasi objek. Bukan hanya OO yang digunakan kebanyakan orang, tapi itu tidak masalah. Orientasi objek adalah tentang kondisi penggandengan dengan metode yang beroperasi pada kondisi itu, itu saja. Tidak mengharuskan setiap objek harus menjadi objek kehidupan nyata atau semacamnya.
Kylotan

@Kylotan: Sekali lagi, saya berbicara secara khusus tentang model-model seperti dijelaskan dalam "Sistem Entitas adalah masa depan pengembangan MMOG", di mana komponen adalah data bodoh yang dioperasikan oleh "sistem" eksternal. Mereka bukan objek karena mereka tidak memiliki perilaku / metode; mereka adalah hubungan (pikirkan baris database atau struct C). Kesetaraan yang salah antara OOP dan penggunaan "objek" sehari-hari tidak ada hubungannya dengan itu. Dari Bagian 3: "Saya tidak suka menggunakan OOP di mana pun dalam implementasi ES; terlalu mudah untuk menyelinap kembali beberapa OOP di tempat yang tidak pantas dan menipu diri sendiri untuk berpikir bahwa ini adalah Ide yang Baik."
Dave Sherohman

Saya mengetahui artikel ini, tetapi ini hanya pendapat satu orang tentang bagaimana hal-hal ini harus dilakukan - ini bukan cara standar, atau tentu saja cara terbaik, jadi tidak benar untuk mengatakan bahwa desain yang digerakkan oleh komponen adalah sepenuhnya berbeda paradigma pemrograman. Sangat mungkin - dan jauh lebih umum - untuk mengimplementasikan arsitektur berbasis komponen dengan kode OO, dan menggunakan kode OO sama sekali tidak merusak "komponen" itu lebih daripada menggunakan prosedur yang tersimpan merusak aspek relasional dari database. .
Kylotan

@Dave, pertanyaan ini sama sekali bukan tentang sistem entitas-komponen. ES maupun desain berbasis data bukanlah OO, itu adalah kesalahan yang umum, tetapi besar untuk mengasumsikan demikian. jika Anda google untuk itu Anda akan menemukan beberapa artikel bagus mengungkap mitos ini. Namun, pertanyaan ini adalah tentang prinsip-prinsip OO umum tentang bagaimana merancang objek Anda, pola desain tingkat yang lebih tinggi tidak menjawab pertanyaan itu sama sekali.
Maik Semder

0

Saya memperbarui jawaban saya karena banyak hal yang tidak jelas sebelum komentar. Tolong telanjang dengan saya saat saya menjelaskan pikiran saya.

Secara umum, dua aspek utama untuk dipertimbangkan dalam desain apa pun adalah kohesi dan kopling . Kita semua tahu bahwa kita membutuhkan kohesi yang tinggi dan kopling yang rendah untuk dapat membuat desain yang lebih dapat digunakan kembali dan diperluas.

Jadi, jika dunia harus mengatur segalanya, itu berarti ia memiliki kohesi yang rendah dan kopling yang ketat (karena itu perlu mengetahui dan melakukan segalanya). Namun, ini juga merupakan kasus ketika entitas game harus melakukan segalanya. Perbarui lokasinya, render teksturnya, dll. Dll

Apa yang benar-benar Anda minati adalah menciptakan sistem yang fokus pada satu aspek entitas. Misalnya, entitas game dapat memiliki Tekstur, tetapi Renderer akan bertanggung jawab untuk membuat tekstur itu di layar. Renderer tidak peduli dengan properti lain yang dimiliki entitas.

Mengambil sedikit lebih jauh, entitas permainan hanyalah sekumpulan properti. Properti ini dimanipulasi oleh sistem yang berfokus pada properti tertentu. Dan ini adalah tempat Sistem Entitas Berbasis Komponen (CBES) masuk, di mana properti = komponen.

Secara khusus, CBES dengan Sistem (atau SubSistem). Desain ini cenderung memiliki beberapa Sistem yang berfokus pada komponen spesifik suatu entitas sementara tidak peduli tentang apa komponen lain yang dimiliki entitas. Juga, Sistem hanya digabungkan dengan informasi yang mereka butuhkan untuk memproses komponen-komponen ini.

Mari kita ambil contoh. Karena input tempat untuk memindahkan entitas didasarkan pada pengontrol pemain, Anda mungkin akan memiliki PlayerControllerSystem. Sistem ini, akan mengendalikan, terlepas dari banyak hal lain, PositionComponent entitas. Dalam hal ini, PlayerControllerSystem perlu mengetahui tentang Level dan PositionComponent. Jika nanti Anda memutuskan untuk menambahkan deteksi tabrakan, Anda akan membuat CollisionSystem yang akan lagi menggunakan posisi entitas, tetapi kali ini untuk menghitung kotak pembatas (atau Anda bisa memiliki BoundingBoxComponent, panggilan Anda). Faktanya adalah, Anda dapat dengan mudah mengaktifkan atau menonaktifkan perilaku (bahkan dengan cepat) hanya dengan menambahkan / menghapus komponen. Jadi, lebih banyak perilaku berarti lebih banyak sistem memanipulasi komponen suatu entitas, tetapi mereka semua berada dalam kelas yang didefinisikan dengan baik dengan kopling rendah. Ingin membuat skrip? Tambahkan ScriptComponent. BAM! Anda baru saja menambahkan kemampuan scripting dengan 2 kelas. Fisika? Suara? Sama lagi.

Jadi, alasan saya mengadvokasi CBES dengan SubSystems adalah bahwa itu adalah OO yang sempurna dan keseluruhan sistem yang mudah dikelola / diperluas. Menambahkan perilaku ke suatu entitas sesederhana memutuskan data apa yang dibutuhkan perilaku dan entitas mana yang membutuhkannya.

Untuk informasi lebih lanjut tentang Sistem Entitas berbasis Komponen dengan SubSistem, ada serangkaian posting blog yang sangat baik oleh T = Machine di Entity Systems adalah masa depan pengembangan MMOG . Penulis bahkan membuat wiki untuk mengumpulkan berbagai implementasi bernama Entity Systems Project

Pos umum (dan terkenal) tentang Sistem Entitas Berbasis Komponen secara umum adalah Evolve hierarki Anda yang menciptakan sistem untuk Tony Hawk Pro.

Akhirnya, jika Anda mencari perpustakaan dengan kode contoh, jangan melangkah lebih jauh dari perpustakaan Artemis . Artemis terutama di Jawa tetapi di sini adalah port di C # (yang saat ini saya gunakan dalam proyek XNA saya).


2
-1, karena ini tidak menyelesaikan masalah, hanya memindahkannya. Dia masih tidak akan memiliki jawaban yang jelas mengenai objek mana yang mengambil keputusan, apakah itu terdiri dari komponen atau tidak.
Kylotan

1
Tautan kedua menyediakan tutorial yang luas tentang mengapa perilaku entitas game harus dieksternalisasi ke Entity Systems. Artemis mengikuti arsitektur yang persis sama.
pek

Tautan kedua adalah sebuah opini. Komponen disukai oleh banyak orang tetapi mereka bukan solusi untuk semua masalah, dan mereka jelas tidak memiliki solusi intrinsik untuk yang satu ini.
Kylotan

Jawaban yang paling banyak dipilih dalam pertanyaan ini dimulai, "Tidak ada jawaban yang sederhana. Seperti kebanyakan hal dalam pemrograman, ini merupakan pertukaran." Tautan kedua menyediakan salah satu dari banyak solusi. Bahkan, ia menganjurkan kebalikan dari jawaban itu. Mungkin saya harus mengedit jawaban saya untuk membuatnya lebih jelas. Tetapi sekali lagi, mungkin ini tidak akan mengubah suara negatif: P
pek

@ pek: Downvote saya adalah karena "gunakan komponen" bukan jawaban untuk pertanyaan ini. Saya memang menggunakan komponen, dan saya merekomendasikan pola komponen, tetapi "menggunakan sistem entitas berbasis komponen" bukanlah jawaban untuk setiap masalah dalam pengembangan game, atau bahkan dalam arsitektur perangkat lunak game - pertanyaan ini muncul sama dengan komponen atau warisan hierarki atau tipe entitas statis yang sama sekali tidak terkait!

0

Saya biasanya pergi dengan desain di mana objek menangani diri mereka sendiri (itu adalah metode untuk, setelah semua) tetapi Dunia dasar memiliki daftar semua objek dan menggunakan daftar tersebut untuk mengoordinasikannya. Jadi sesuatu seperti:

class World {
  var walls = [];
  var actors = [];
  function update() {
    for each (actor in actors) {
      actor.update(walls);
    }
  }
}

class Actor {
  function update(walls) {
    this.move();
    for each (wall in walls) {
      this.collide(wall);
    }
  }
}

0

Tetap KERING, pemalu dan beri tahu orang lain.

Lebih baik meminta dunia untuk memindahkan aktor Anda daripada bertanya kepada dunia apakah Anda bisa pindah ke tempat yang ingin Anda tuju. Dengan cara ini Anda dapat mengubah algoritme pathfinding dengan mudah di kelas dunia dan semacamnya. Tentu saja, Anda bisa menyerahkan ini pada baseclass untuk aktor, tapi itulah arahan yang akan saya ambil dan alasan mengapa.


-1

EDIT: Ditulis ulang karena umpan balik yang menyatakan saya belum menarik garis yang cukup jelas untuk jawaban pertanyaan awal ini.

Saya ingin mengklarifikasi pertanyaan sedikit lebih banyak jika memungkinkan. Haruskah logika yang bertindak atas suatu objek bersifat internal atau eksternal terhadap objek itu. Bagian terakhir dari pos secara khusus menyebutkan tentang umur panjang desain sebagai dasar untuk mengajukan pertanyaan, untuk menghindari masalah di kemudian hari.

Jawaban tingkat tinggi sederhana saya adalah untuk menjaga semua logika yang bertindak atas suatu objek di dalam objek itu.

Anda tidak perlu dunia untuk memindahkan objek, yang Anda butuhkan hanyalah objek yang akan dipindahkan dan vektor yang mewakili lokasi untuk dipindahkan. Dunia mungkin ikut bermain ketika suatu destinasi dipilih atau ketika reaksi terhadap lingkungan diperlukan karena tabrakan, tetapi itu adalah di luar contoh yang diberikan untuk dikerjakan.

Untuk mengatasi bagian mendasar dari pertanyaan dan mencapai umur panjang dari desain saya akan menyarankan arsitektur berorientasi komponen. Arsitektur komponen memecah suatu objek menjadi set data dan fungsionalitas diskrit (dengan asumsi Anda pergi dengan jawaban saya di atas yang menyatakan untuk menjaga logika dengan data). Jika struktur Anda terlihat seperti CEntity-> CHuman-> CSoldier-> CPlayerCharacter maka Anda akan selalu masuk ke masalah di mana Anda perlu mengubah beberapa logika dan tergantung di mana masuknya pohon itu (Berapa banyak jenis manusia yang ada misalnya?) itu dapat memiliki efek menyapu pada beberapa jenis objek.

Sistem komponen sebaliknya akan memiliki satu set antarmuka yang mendefinisikan objek CEntity terdiri dari seperti ICompRenderable, ICompMoveable, ICompHealth, ICompInventory dan sebagainya. Di mana Anda memiliki CCompMoveableHuman dan mungkin CCompMoveableSoldier dan CCompMoveablePlayer untuk menjaga pola gerakan masing-masing terpisah. Jadi katakanlah Prajurit diubah untuk berlari dalam formasi. Perubahan ini hanya akan memengaruhi entitas yang dibangun menggunakan komponen itu.

Jadi, singkatnya saya sarankan Anda mengandung logika dengan data yang berlaku untuk logika. Saya juga merekomendasikan memecah benda menjadi komponen diskrit untuk mengurangi 'Di mana saya meletakkan ini?' pertanyaan dan memberikan stabilitas ke masa depan dengan kemudahan perawatan dan diperpanjang.

Semoga ini membantu.


Saya telah melihat ke dalam pola komponen beberapa jam terakhir. (Link pek sangat bagus). Tapi masih belum jelas di mana "perilaku" yang sebenarnya harus terjadi. Jelas bahwa suatu entitas memiliki komponen berbeda untuk input, rendering, fisika. Tetapi jika saya mengerti dengan benar, komponen hanya berisi data yang diperlukan untuk dapat berfungsi, tetapi sebenarnya tidak mengandung implementasi. Mari kita kembali ke langkah lagi; Bagaimana saya harus membuat entitas bergerak menggunakan komponen? Haruskah saya memperluas komponen input dan kode implementasi di sana? Atau sesuatu yang lain mengelola implementasi?
omgnoseat

Bagi saya, saya menyimpan logika di objek, tetapi saya benar-benar melakukan sistem komponen di atas Desain Berorientasi Data yang berarti sebagian besar objek saya sebenarnya hanya logika yang dipetakan ke lokasi di dalam data untuk pemrosesan cepat yang bersebelahan ... Dan pada akhirnya, pelajari satu pola desain pada satu waktu: D Adapun -1, akan sangat menghargai mengetahui mengapa itu ditandai seperti itu, bahkan jika itu hanya 'Saya suka jawaban saya lebih baik' Saya masih ingin tahu kenapa.
James

1
@ James, cukup adil. Saya downvoted karena sistem entitas-komponen tidak menjawab pertanyaan awal. Komponen posisi masih dapat bergerak sendiri atau dunia dapat beralih ke semua komponen posisi dan memindahkannya. Alasan yang sama Kylotan memilih jawaban pek, jadi saya pikir alasan -1 jelas. Dan bahkan jika itu akan menjadi keharusan bagi sistem komponen untuk memindahkan dirinya sendiri (yang bukan kasusnya) itu masih tidak akan menjadi jawaban, hanya kasus penggunaan untuk 1 opsi. Tetapi pertanyaannya adalah tentang alasan untuk menggunakan satu atau yang lain, pro dan kontra mereka. Jawabannya tidak mencakup itu.
Maik Semder

@Maik Semder. Terima kasih untuk umpan baliknya. Saya telah menulis ulang jawaban untuk mencoba dan menggambar garis-garis yang lebih jelas pada pertanyaan awal dan dorongan keseluruhan untuk itu di tempat pertama seperti yang diberikan pada akhir pertanyaan.
James

@ James, terima kasih telah meluangkan waktu untuk mengedit jawaban dalam menanggapi komentar saya, sangat dihargai. Jawaban yang diajukan untuk "menjaga semua logika yang bertindak atas suatu objek di dalam objek itu" mengalahkan fitur inti OO, yaitu enkapsulasi. Seperti yang ditunjukkan oleh tautan Joe, menggunakan fungsi bukan-teman bukan-anggota meningkatkan tingkat enkapsulasi suatu objek. Selain itu, ia memperkenalkan metode yang jelas sebagai cara mengukur enkapsulasi. Menempatkan fungsi-gerak ke dunia atau aktor mengurangi enkapsulasi desain, sehingga kurang fleksibel dan sulit untuk mempertahankan kode.
Maik Semder

-1

Saya sarankan Anda mencoba membaca tentang arsitektur berbasis komponen. Ada beberapa posting blog, presentasi dan menulis di luar sana tentang mereka yang dapat melakukan pekerjaan yang lebih baik daripada yang pernah saya bisa.

AltDevBlogADay memiliki beberapa posting tentang hal itu, yang sangat bagus adalah seri ini tentang entitas game: http://altdevblogaday.com/2011/07/10/the-game-entity-–-part-ia-retrospect/ Ada beberapa bagian yang fokus pada masalah yang Anda coba selesaikan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.