Δημήτρης Κατηφόρης

Η γνώμη μου για το ECS και διάφορα

2024-1-2

Τι είναι το ECS;

Καλησπέρα

καλή χρονιά

καλό μήνα

καλό δίσεκτο έτος

καλή ανάγνωση

καλά να περάσε

καλή τυχή σε εμένα που ως αρχάριος πάω να γράψω άρθρο για κάτι που δεν έχω τελειώσει ακόμα

Δεν πρόκειται για εφαρμογή

Αφού ευχήθηκα ας ξεκαθαρίσω ότι το ECS δεν είναι τίποτα άλλο παρά ένας ωραίος τρόπος να σχεδιάσει κανείς ένα μεγάλο πρόγραμμα. Δεν είναι κάτι συγκεκριμένο, δεν υπάρχει ένα ECS και ο καθένας έχει την ελευθερία να το σχεδιάσει όπως θέλει αρκεί φυσικά να ακολουθεί τις 3 βασικές ιδέες του: να έχει Entities, Components και Systems. Και πάλι βέβαια αμφιλεγόμενο αυτό… υπάρχουν παραδείγματα ECS που συγχωνεύουν components και systems. Για αυτό χαρακτηρίζουμε ένα «σωστό» ECS ως pure, με την έννοια ότι ακολουθεί κατά γράμμα τα standards που η κοινώτητα έχει θέσει με τον καιρό.

Κύρια χαρακτηριστικά

  • Έχουμε entities που είναι απλά ένα integer και χαρακτηρίζουν μια οντότητα στην εφαρμογή μας. Αυτή η οντότητα, μπορεί να είναι τα πάντα, από έναν παίχτη ή ένα particle emittor, ως και ένα timer.
  • Components είναι τα χαρακτηριστικά (και αυτά τα κάνουμε implement ως έναν integer που το διαφοροποιεί από τα υπόλοιπα. Δεν περιέχουν πληροφορίες! ) τα οποία δεν έχουν καμία ουσία από μόνα τους. Όταν όμως τα ενώνουμε με entites (binding, δεν κάνουμε κάτι περίπλοκο, βάζουμε το id τους σε μια λίστα), τότε είναι που φανερώνουν την χρησιμότητά τους. Σε έναν entity που αναπαριστά τον παίχτη ενός παιχνιδιού θα φτιάχναμε και θα βάζαμε ένα health component, ένα damage component και ένα movable component (μεταξύ άλλων). Έτσι λέμε στο engine μας πώς να μεταχειρίζεται από εδώ και στο εξής τον παίχτη entity.
  • Systems είναι functions που λειτουργούν μόνο σε ένα συγκεκριμένο είδος entity. Δηλαδή ένα σύστημα (ας το ονομάσουμε movement_system) θα έκανε iterate όλα τα entities που έχουν το component movable και θα τους άλλαζε την θέση. Είναι αυτά που δίνουν ζωή στο πρόγραμμά μας, είναι το game logic.

Το σχίσμα των δύο εφαρμογών

Ο καθένας επιλέγει τον τρόπο που θα ακολουθείς αυτούς τους τρείς κανόνες έτσι ώστε να φτιάξει το πιο αποδοτικό πρόγραμμα για τις απαιτήσεις του. Όλο το πρόβλημα έγκειται αρχικά στο πώς θα αποθηκεύουμε τα entities ανάλογα με τους συνδυασμούς των components που έχουν. Εδώ έχει μεγάλη σημασία το cache locality μια έννοια με την οποία δεν ήμουν καλά εξοικειωμένος στο παρελθόν. Θέλουμε να βάζουμε τα soon-to-be-iterated entities (εννοώ τις πληροφορίες που έχει το κάθε του component) το ένα δίπλα στο άλλο έτσι ώστε ο επεξεργαστής να μπορεί εύκολα να επεξεργάζεται τα δεδομένα μέσω των systems.

Ένας γνωστός τρόπος να το πετύχουμε αυτό είναι να τοποθετήσουμε τα entities που έχουν ακριβώς το ίδιο είδος και αριθμό components σε ομάδες μέσα στην μνήμη. Εδώ έρχεται η έννοια των tables / archetypes (συνώνυμα) που έχουν επηρεαστεί από τον σχεδιασμό των βάσεων δεδομένων. Κάθε entity αποτελεί μια γραμμή (row ή record) και κάθε στήλη το είδος το component έχει.

Entity id Health Component Position3D Component
1 100 20, 40, 128
3 30 0, 0, 0
27 45 120, 120, 120

Με αυτόν τον τρόπο αποθήκευσης το πρόγραμμά μας αποκτά οργάνωση που δεν διαθέτει έυκολο ούτε το OOP ούτε το σκέτο DoD μακροπρόθεσμα. Το DamageSystem() function θα καλεί άλλη μια συνάρτηση του τύπου get_table_by_type(health_component, position_component) που θα το προμηθεύει με το αντίστοιχο table στο οποίο ύστερα θα μπορεί να κάνει την δουλεία του αν όντως χρειαστεί

for (item in table id) 
{ 
    apply_damage(int entity); 
    move_entity(int id, -10, -10, 0);
}

Το κάθε entity πχ τέρας στο παιχνίδι θα χάνει health και θα ωθείται προς τα πίσω λόγω του χτυπήματος.

Ένας άλλος τρόπος είναι αυτό που εκμεταλλεύεται το O(1) lookup των sparse sets. Από ότι καταλαβαίνω sparse sets χρησιμοποιούνται κατά κανόνα στον χώρο του ECS και αποδεικνύονται αρκετά χρήσιμα για κάθε είδους implementation. Κάποιοι τα επεκτείνουν και τα χρησιμοποιούν ακόμα ώστε να αποθηκεύουν και components (τα δεδομένα των components για κάθε entity δηλαδή).

Γιατί το κάνουμε όλο αυτό;

Όλοι μας, ακόμα και αυτοί με λιγότερη πείρα όπως εγώ, έχουμε φτάσει στο σημείο κάποτε να κουραζόμαστε να βάζουμε καινούργια features σε ένα πρόγραμμά μας λόγω της συσσώρευσης του κωδικού, είτε το κάνουμε σε c++ με inheritance είτε το κάνουμε σε c. Η διαχείριση των προγραμμάτων γίνεται ολοένα και δυσκολότερη και δεν υπάρχει έυκολος τρόπος να το διορθώσουμε αυτό, όσο modular και αν είναι ο κωδικός μας. Εδώ έρχεται το ECS για να μας βοηθήσει.

Χωρίς αμφιβολία, δεν μας κάνει τον κωδικό γρηγορότερο. Εδώ δεν μιλάμε για performance μιλάμε για sustainability. Ναι, στην αρχή το πρόγραμμά μας θα πρέπει αν φορτώσει όλο το engine που φτιάξαμε, ακόμα και για να εμφανίσει ένα κουτί στην οθόνη. Δεν σημαίνει όμως αυτό ότι μετά από 1-2 μήνες δεν είμαστε ευγνώμων για την ύπαρξή του game engine μας.

Το άρθρο πρόκειται να αναβαθμιστεί στο μέλλον

Αυτό που λέει ο τίτλος. Να το ανεβάσω στο beginners ή στο help; Είμαι καινούργιος στο forum συγγνώμη για την ενόχληση @-@

Ναι… Μένουν ακόμα πολλά να διαβάσω. Είναι πολύ ενδιαφέρον, να το δεις πάντως. Στείλε μου και κανένα email αν βρεις κάτι ενδιαφέρον

Κατηγορίες:

Η γνώμη μου για το ECS και διάφορα

Οι μοντέρνοι δυτικοί έχουν μάθει να αγνοούν την ιδέα της φυλετικής ιεραρχίας. Είναι σοκαρισμένοι από τους νόμους που απαγορεύουν στους μαύρους να περπατούν στους δρόμους των λευκών, ή να διαβάζουν στα σχολεία των λευκών, ή να εξυπηρετούνται σε νοσοκομεία των λευκών. Αλλά η ιεραρχία των πλουσίων και των φτωχών, που υποχρεώνει τους πλούσιους να ζουν σε διαφορετικές γειτονίες, πιο πολυτελείς, να διαβάζουν σε σχολεία διαφορετικά και πιο προνομιούχα, ή να θεραπεύονται σε ιδιωτικές κλινικές, καλύτερα εξοπλισμένες, φαίνεται τελείως δικαιολογημένη στα μάτια πολλών Αμερικανών και Ευρωπαίων

Harari Yuvah-Noah, Sapiens