Dalam merancang sistem entitas-komponen untuk mesin saya, saya telah menemukan sedikit hambatan dalam cara menyimpan dan mengambil jenis komponen tertentu.
Pertama, izinkan saya mengatur sedikit terminologi yang akan saya gunakan dalam pertanyaan ini:
- Saya menyebut " Komponen " struktur data yang menyimpan data yang relevan untuk sistem tertentu.
- Saya menyebut " Sistem " agregasi metode dan struktur data yang memanfaatkan Komponen untuk memperbarui status permainan / antarmuka dengan pengguna.
- " Entity " pada dasarnya hanya ID yang digunakan untuk mengambil komponen tertentu dan memodifikasi data mereka dalam logika game.
Setiap sistem memiliki larik (ID-dipetakan) dari jenis Komponennya (Misalnya Fisika-> Komponen Fisika, AI-> Komponen A, komponen- Render-> RenderingKomponen), sehingga dapat beralih secara efisien melalui data.
Namun, tidak semua komponen dimiliki secara khusus oleh suatu sistem. Misalnya, komponen Transform menyimpan posisi, rotasi, dan skala objek. Ini adalah salah satu bagian terpenting dari sebuah entitas (Unity membuatnya wajib, bahkan), karena digunakan oleh banyak sistem, misalnya Fisika, AI, Rendering dll.
Ini cukup banyak masalah yang saya hadapi. Karena Transform digunakan oleh banyak sistem lain, bagaimana cara saya mengambil satu untuk digunakan untuk setiap Komponen? Salah satu solusi yang mungkin saya lihat adalah membuat setiap Komponen menyimpan ID Entitasnya sendiri. Akan mudah untuk mengambil komponen seperti ini, tetapi tidak akan seefisien itu, dan itu juga akan bertentangan dengan konsep Komponen sebagai kumpulan data yang terisolasi dan independen, yang tidak mengetahui komponen lainnya.
Apakah ada cara yang tepat untuk menyelesaikan masalah ini? Haruskah Transform bahkan menjadi komponen?
sumber
Jawaban:
Ini adalah pertanyaan yang cukup luas, jawabannya, sangat tergantung pada arsitektur Anda. Namun, saya akan berusaha memberi Anda jawaban umum.
Fisika dan sistem rendering Anda tentu membutuhkan transformasi, namun, sistem AI tidak akan melakukannya. Oleh karena itu, masuk akal untuk merangkum transformasi ke kelas komponen itu sendiri. Semua sistem yang tertarik tersebut akan menggunakan data yang sama, oleh karena itu, masuk akal bagi entitas untuk memiliki pointer ke objek transformasi, atau id untuk objek transformasi yang disimpan di tempat lain.
Jika Anda memilih solusi yang terakhir, maka setiap sistem yang tertarik pada transformasi akan memerlukan akses ke mana pun objek transformasi disimpan.
Jika Anda memilih yang pertama, maka yang perlu dilakukan setiap sistem adalah mengakses entitas itu sendiri, dan meminta transformasi.
Dalam kasus sebelumnya, masalahnya menjadi bagaimana memberikan akses ke penyimpanan untuk transformasi ke setiap sistem, tanpa melanggar aturan OOP, jika Anda peduli tentang hal-hal seperti itu.
Kasing terakhir tidak memiliki masalah seperti itu, tetapi membutuhkan perubahan desain objek entitas Anda untuk menyimpan pointer ke objek daripada id objek komponen.
Preferensi pribadi saya adalah merancang kelas entitas untuk menyimpan pointer ke objek komponen, karena menyederhanakan banyak masalah desain. Dengan cara ini, setiap sistem yang membutuhkan transformasi dapat memintanya dari entitas, dan mengabaikannya jika tidak. Namun, ini membawa overhead komputasi yang melekat pada pointer, yang menjadi biaya cache gagal.
Lihat Ikhtisar ECS ini untuk informasi lebih lanjut tentang ini.
Pada akhirnya, terserah Anda untuk memutuskan mana yang lebih penting bagi Anda: kemudahan pengembangan, atau kinerja.
Saya akan menunjukkan, akhirnya, bahwa pertanyaan Anda adalah contoh yang sangat baik dari pertanyaan desain yang dipikirkan oleh para pendukung ECS, dan tidak ada solusi peluru perak yang pasti.
sumber