ENTITY COMPONENT SYSTEM COMPOSITION OVER INHERITANCE An alternative

  • Slides: 8
Download presentation
ENTITY COMPONENT SYSTEM

ENTITY COMPONENT SYSTEM

COMPOSITION OVER INHERITANCE • An alternative to OOP inheritance • e. g. the Component

COMPOSITION OVER INHERITANCE • An alternative to OOP inheritance • e. g. the Component structure of Unity • Avoids Java-like inheritance trees • e. g. Doom 3 (from “One Weird Trick to write better code” id. Class id. Entity id. Animated. Entity id. Weapon id. AFEntity_Base id. AFEntity_Claw. Four. Fingers id. AFEntity_Vehicle. Four. Wheels id. AFEntity_Vehicle. Six. Wheels id. AFEntity_Gibbable id. AFEntity_With. Attached. Head id. Actor id. Player id. AI • Why is this bad (not everyone would think it’s bad…)? • See https: //en. wikipedia. org/wiki/Composition_over_inheritance for more. . .

IN SSUGE • We’ll have a Game. Object class • Contain a transform (Scene.

IN SSUGE • We’ll have a Game. Object class • Contain a transform (Scene. Node) • Can be parented (again, Scene. Node) • Other info (e. g. tag, resource group, etc. ) • We’ll have a base Component class • An abstract class – meant only to be a base • We’ll derive multiple types of Components from it • Mesh. Component • GUIElement. Component • Particle. Emitter. Component • When setting up our scene, we can “snap-in” a component to add functionality to a Game. Object

C++ POLYMORPHISM • What is the output? class Yarg { public: void func() {

C++ POLYMORPHISM • What is the output? class Yarg { public: void func() { cout << “Yarg” << endl; } }; optional, but nice (like the @Override annotation in Java) class Tango : public Yarg { public: void func() override { cout << “Tango” << endl; } }; Yarg * y = new Yarg(); Tango * t = new Tango(); y->func(); t->func(); delete y; y = t; // Valid b/c of POLYMORPHISM y->func();

A FIX… • You can make a method virtual: • Makes the compiler wait

A FIX… • You can make a method virtual: • Makes the compiler wait until run-time to determine the method to call. • Adds a virtual function table to the object (a little overhead) • Syntax: class Yarg { public: virtual void func() { cout << “Yarg” << endl; } }; • Now it’ll work “better”

PURE VIRTUAL • You can choose to not implement a method in the base

PURE VIRTUAL • You can choose to not implement a method in the base class • …and force the child class to define it. • A little like Java interface classes • The base class is now abstract • We can’t make instances of it. • We can, however, use polymorphic pointers of the base type • Syntax: class Yarg { public: virtual void func() { cout << “Yarg” << endl; } = 0; };

WHY? • In our ECS, I want to have a collection of Component pointers

WHY? • In our ECS, I want to have a collection of Component pointers • But…they’re not actually pointing to Components • …instead they’re pointing to Mesh. Components, etc. • Design Decision • What kind of collection: array (fixed size or not? ), map, vector? • Duplicate component types? • A create. XYZ method in Game. Object vs. an add. Component(Component*) method.

FACTORIES • Another common design pattern • Used to create instances of another class

FACTORIES • Another common design pattern • Used to create instances of another class • In C++ • Could be • a separate class (e. g. Mesh. Component. Factory – probably a Singleton) • a static method (e. g. in the Mesh. Component class) • Advantages: • Can optimize memory allocations • [side-topic]: memory fragmentation and new operator • Isolates code to create instances of that class to one spot • (for us) could update all components “in parallel”