Saat ini saya sedang mencoba untuk mengimplementasikan sistem entitas berbasis komponen, di mana suatu entitas pada dasarnya hanya ID dan beberapa metode pembantu yang mengikat sekelompok komponen bersama-sama untuk membentuk objek permainan. Beberapa tujuan itu antara lain:
- Komponen hanya berisi keadaan (mis. Posisi, kesehatan, jumlah amunisi) => logika masuk ke "sistem", yang memproses komponen-komponen ini dan keadaannya (mis. PhysicsSystem, RenderSystem, dll.)
- Saya ingin mengimplementasikan komponen dan sistem baik dalam C # murni dan melalui scripting (Lua). Pada dasarnya saya ingin dapat mendefinisikan komponen dan sistem yang sepenuhnya baru secara langsung di Lua tanpa harus mengkompilasi ulang sumber C # saya.
Sekarang saya sedang mencari ide tentang bagaimana menangani hal ini secara efisien dan konsisten, jadi saya tidak perlu menggunakan sintaks yang berbeda untuk mengakses komponen C # atau komponen Lua, misalnya.
Pendekatan saya saat ini adalah mengimplementasikan komponen C # menggunakan properti publik biasa, mungkin dihiasi dengan beberapa atribut yang memberi tahu editor tentang nilai dan hal-hal standar. Lalu saya akan memiliki kelas C # "ScriptComponent", yang hanya membungkus tabel Lua secara internal dengan tabel ini dibuat oleh sebuah skrip dan menahan semua status jenis komponen tertentu. Saya tidak benar-benar ingin mengakses keadaan itu banyak dari sisi C #, karena saya tidak akan tahu pada waktu kompilasi, apa ScriptComponents dengan properti apa yang akan tersedia untuk saya. Namun, editor perlu mengaksesnya, tetapi antarmuka sederhana seperti berikut ini sudah cukup:
public ScriptComponent : IComponent
{
public T GetProperty<T>(string propertyName) {..}
public void SetProperty<T>(string propertyName, T value) {..}
}
Ini hanya akan mengakses tabel Lua dan mengatur dan mengambil properti-properti itu dari Lua dan itu dapat dengan mudah dimasukkan dalam komponen C # murni juga (tetapi gunakan properti C # biasa kemudian, melalui refleksi atau sesuatu). Ini hanya akan digunakan dalam editor, bukan oleh kode game biasa, jadi kinerja tidak sepenting di sini. Ini akan membuatnya perlu untuk menghasilkan atau menulis beberapa deskripsi komponen yang mendokumentasikan properti apa yang sebenarnya ditawarkan oleh tipe komponen tertentu, tetapi itu tidak akan menjadi masalah besar dan bisa cukup otomatis.
Namun, bagaimana cara mengakses komponen dari sisi Lua? Jika saya melakukan panggilan ke sesuatu seperti getComponentsFromEntity(ENTITY_ID)
saya mungkin hanya akan mendapatkan banyak komponen C # asli, termasuk "ScriptComponent", sebagai data pengguna. Mengakses nilai dari tabel Lua yang dibungkus akan menghasilkan saya memanggil GetProperty<T>(..)
metode daripada mengakses properti secara langsung, seperti dengan komponen C # lainnya.
Mungkin menulis getComponentsFromEntity()
metode khusus hanya untuk dipanggil dari Lua, yang mengembalikan semua komponen C # asli sebagai userdata, kecuali untuk "ScriptComponent", di mana ia akan mengembalikan tabel yang dibungkus. Tetapi akan ada metode lain yang berhubungan dengan komponen dan saya tidak benar-benar ingin menduplikasi semua metode ini baik untuk dipanggil dari kode C # atau dari skrip Lua.
Tujuan utamanya adalah menangani semua jenis komponen dengan cara yang sama, tanpa sintaksis kasus khusus yang membedakan antara komponen asli dan komponen Lua - terutama dari sisi Lua. Misalnya saya ingin dapat menulis skrip Lua seperti itu:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Script seharusnya tidak peduli komponen apa yang sebenarnya didapat dan saya ingin menggunakan metode yang sama yang saya gunakan dari sisi C # untuk mengambil, menambah atau menghapus komponen.
Mungkin ada beberapa contoh implementasi mengintegrasikan scripting dengan sistem entitas seperti itu?