Saat ini saya sedang membuat proyek hobi kecil untuk kembali ke pengembangan game, dan saya telah memutuskan untuk membuat struktur entitas saya menggunakan ECS (Entity Component System). Implementasi ECS ini disusun seperti:
- Entitas : Dalam kasus saya ini adalah
int
pengidentifikasi unik yang digunakan sebagai kunci untuk daftar komponen. - Komponen : Memegang hanya data, mis.
Position
Komponen menampungx
dany
mengoordinasikan, danMovement
komponen menyimpanspeed
dandirection
variabel. - Sistem : Menangani komponen, misalnya dibutuhkan
Position
danMovement
komponen dan menambahkanspeed
dandirection
ke posisi inix
dany
koordinat.
Ini berfungsi dengan baik, tapi sekarang saya ingin menerapkan skrip ke dalam permainan saya, dalam bentuk bahasa scripting. Dalam proyek-proyek sebelumnya saya telah menggunakan implementasi OOP objek game, yang berarti bahwa scripting cukup lurus ke depan. Misalnya, skrip sederhana dapat terlihat seperti ini:
function start()
local future = entity:moveTo(pos1)
wait(future)
local response = entity:showDialog(dialog1)
if wait(response) == 1 then
local itemStack = entity:getInventory():removeItemByName("apple", 1)
world:getPlayer():getInventory():addItemStack(itemStack)
else
entity:setBehavior(world:getPlayer(), BEHAVIOR_HOSTILE)
end
end
Namun, ketika menggunakan ECS, entitas itu sendiri tidak memiliki fungsi seperti moveTo
atau getInventory
, sebaliknya skrip di atas yang ditulis dengan gaya ECS akan terlihat seperti ini:
function start()
local movement = world:getComponent(MOVEMENT, entity)
movement:moveTo(pos1)
local position = world:getComponent(POSITION, entity)
local future = Future:untilEquals(position.pos, pos1)
wait(future)
local dialogComp = world:getComponent(DIALOG, entity)
local response = dialogComp:showDialog(dialog1)
if wait(response) == 1 then
local entityInventory = world:getComponent(INVENTORY, entity)
local playerInventory = world:getComponent(INVENTORY, world:getPlayer())
local itemStack = entityInventory:removeItemByName("apple", 1)
playerInventory:addItemStack(itemStack)
else
local entityBehavior = world:getComponent(BEHAVIOR, entity)
local playerBehavior = world:getComponent(BEHAVIOR, world:getPlayer())
entityBehavior:set(playerBehavior, BEHAVIOR_HOSTILE)
end
end
Ini jauh lebih banyak verbose dibandingkan dengan versi OOP, yang tidak diinginkan ketika skrip ditujukan untuk sebagian besar non-programmer (pemain game).
Salah satu solusinya adalah memiliki semacam objek pembungkus yang merangkum Entity
dan memasok fungsi-fungsi seperti moveTo
secara langsung, dan menangani sisanya secara internal, meskipun solusi semacam itu tampaknya kurang optimal karena butuh banyak pekerjaan untuk mencakup semua komponen, dan setiap saat komponen baru ditambahkan, Anda perlu mengubah objek pembungkus dengan fungsi baru.
Untuk semua pengembang game yang telah mengimplementasikan skrip di ECS sebelumnya - bagaimana Anda melakukannya? Fokus utama di sini adalah kegunaan untuk pengguna akhir, dengan biaya "pemeliharaan" sesedikit mungkin (sebaiknya Anda tidak perlu mengubahnya setiap kali Anda menambahkan komponen).
sumber
System
kelas / s untuk memungkinkan komponen tetap struct data.moveTo
metode ini sebagai bagian dari sistem yang mendasari dalam kasus penggunaan Anda, misalnya MovementSystem? Dengan cara ini Anda tidak hanya dapat menggunakannya dalam skrip yang Anda tulis, tetapi Anda juga dapat menggunakannya sebagai bagian dari kode C ++ di mana pun Anda membutuhkannya. Jadi ya Anda harus memaparkan metode baru ketika sistem baru ditambahkan, tapi itu diharapkan sebagai perilaku yang sama sekali baru yang diperkenalkan sistem ini.Jawaban:
Anda bisa membuat sistem ScriptExecutionSystem yang beroperasi di semua entitas dengan komponen Script. Ia memperoleh semua komponen entitas yang dapat berguna untuk mengekspos ke sistem scripting dan meneruskannya ke fungsi scripted.
Pendekatan lain adalah membuat pengguna Anda juga merangkul ECS dan memungkinkan mereka untuk mendefinisikan komponen mereka sendiri dan menerapkan sistem mereka sendiri menggunakan bahasa scripting.
sumber
ECS memiliki pro dan kontra. Skrip yang mudah digunakan bukan salah satu kelebihannya.
Masalah yang dipecahkan ECS adalah kemampuan untuk memiliki banyak hal serupa dalam gim Anda pada saat bersamaan sambil mempertahankan kinerja. Tetapi solusi ini datang dengan biaya - biaya arsitektur yang mudah digunakan. Ini bukan arsitektur terbaik untuk setiap game.
Sebagai contoh, ECS akan menjadi pilihan yang baik untuk Space Invaders , tetapi tidak begitu banyak untuk PacMan .
Jadi bukan jawaban yang Anda cari, tetapi mungkin ECS bukan alat yang tepat untuk pekerjaan Anda.
Jika Anda menambahkan pembungkus, perhatikan biaya overhead. Jika Anda akhirnya menghapus peningkatan kinerja ECS di bungkus Anda, maka Anda memiliki yang terburuk dari kedua dunia.
Tetapi untuk langsung menjawab pertanyaan Anda - "Untuk semua pengembang game yang telah mengimplementasikan scripting di ECS sebelumnya - bagaimana Anda melakukannya?"
Sama persis seperti yang Anda lakukan, tanpa bungkus. Entitas tidak memiliki apa pun selain pengidentifikasi. Komponen tidak memiliki apa-apa selain data. Sistem tidak memiliki apa pun kecuali logika. Sistem yang menerima entitas dengan komponen yang diperlukan dijalankan. Tambahkan sistem, entitas, dan komponen secara bebas.
Saya pernah menggunakan kerangka kerja dengan aspek keempat, yang disebut papan tulis. Itu pada dasarnya adalah cara bagi sistem untuk berkomunikasi dengan satu sama lain. Itu menciptakan lebih banyak masalah daripada yang dipecahkan.
Terkait: Haruskah saya menerapkan Sistem Komponen Entitas di semua proyek saya?
sumber
Dengan ECS Anda dapat memecah menjadi satu tanggung jawab, sehingga setiap entitas yang bergerak akan menginginkan dua komponen data: a MoveComponent, dan MoveSpeedComponent.
jadi sekarang dalam konversi Anda menambahkan komponen-komponen itu ke entitas Anda
Sekarang setelah kita memiliki konversi dan data yang dapat kita pindahkan ke sistem, saya menghapus sistem input agar mudah dibaca tetapi jika Anda ingin mempelajari lebih lanjut tentang sistem input, saya akan memiliki semuanya tercantum dalam artikel saya minggu depan di unity connect.
perhatikan bahwa kelas di atas menggunakan Unity.Mathmatics. Ini bagus untuk dapat menggunakan berbagai fungsi matematika yang biasa Anda gunakan dalam sistem normal. Dengan itu semua sejalan Anda sekarang dapat bekerja pada perilaku entitas - lagi saya menghapus input di sini tapi ini semua jauh lebih baik dijelaskan dalam artikel.
Sekarang Anda dapat memperkenalkan entitas yang akan bergerak maju dengan cepat.
Tetapi juga ini akan memindahkan setiap entitas dengan perilaku ini sehingga Anda dapat memperkenalkan tag, misalnya jika Anda menambahkan PlayerTag, maka hanya entitas dengan playerTag IComponentData yang akan dapat melakukan MoveForward jika saya hanya ingin memindahkan pemain seperti contoh di bawah.
Saya akan membahas lebih dalam pada artikel tersebut, tetapi kelihatannya seperti ini di ComponentSystem yang khas
Banyak dari hal ini dijelaskan dengan cukup baik dalam presentasi Angry Dots dengan Mike Geig, jika Anda belum melihat saya sarankan untuk memeriksanya. Saya akan menunjukkan artikel saya juga setelah terserah. Seharusnya benar-benar membantu untuk mendapatkan beberapa hal yang biasa Anda kerjakan sesuai keinginan Anda di ECS.
sumber