2

So I'm developing my first game engine and I've hit a wall. Currently I have an Entity base class that has a vector of component pointers which will hold pointers to component objects within some system manager classes (graphisManager, PhysicsManager, etc.). Here is my current Entity header (stripped down to focus on main issue):

Entity.h

class Component;

namespace BlazeGameWorld
{
    class Entity
    {
    public:
        BlazeFramework::Math::Vector2D position;

    protected:
        Vector<Component*> components;

        static BlazeGraphics::GraphicsManager graphicsManager;
        static BlazePhysics::PhysicsManager physicsManager;
        static BlazeInput::InputManager inputManager;
        //....other managers

    private:

        ///////////////////////////////////////////////////////////////////////

    public:
        Entity();
        ~Entity();

        virtual bool Initialize();
        virtual bool Shutdown();

        virtual void Update() = 0;

        void AddComponent(Component* p_component);

        //Part of the broadcast messaging system for components to be able
        //to talk to one another in a decoupled way.
        void SendMessage(uint messageID);

    protected:

    private:
    };
}

As you can see, the idea is to have static SystemManager classes which will manage pointers to the actual components on the heap. Here is a rough Header for the potential PhysicsManager class (and it's similar for the other Manager classes):

PhysicsManager.h

class PhysicsComponent;

namespace BlazePhysics
{
    class PhysicsManager
    {
    public:

    protected:
        int numPhysicsComponents;
    private:
        Vector<PhysicsComponent*> physicsComponents;

        /////////////////////////////////////////////////////////////

    public:
        PhysicsManager();
        ~PhysicsManager();

        bool Initialize();
        bool Shutdown();

        void Update();

        template <typename PhysicsComponentType>
        PhysicsComponentType* CreatePhysicsComponent();

    private:
    };

    //template definitions
    template <typename PhysicsComponentType>
    PhysicsComponentType* PhysicsManager::CreatePhysicsComponent()
    {
        PhysicsComponentType* physicsComponent = new PhysicsComponentType
        physicsComponents.push_back(physicsComponent);

        return physicsComponents.at(numPhysicsComponents++);
    }
}

So I can store all different physicsComponent pointers in the PhysicsManger vector (pointers to CollisionComponents, PositionComponents, etc). The issue is if I wanted to call a method specific to a specific physics component, I can't compile. For example, if (in the update loop for PhysicsManager) I wanted to update a collisionComponent's CheckCollision() method each frame I can't just say in a for loop physicsComponents.at(i).CheckCollisionbecause the compiler doesn't know at compile time what a CollisionComponent is. Is there a way to maybe deduce the type of the component in the array first and then if it matches CollisionComponent call the CheckCollision method? Or is there a better to implement this since this seems kind of clunky?

Jason
  • 2,198
  • 3
  • 23
  • 59
  • Good to see a component based engine here, I'm also working on my first game engine with a similar structure as yours. However, I passed a reference of game engine to each system so they can use the reference to access other systems. I don't know if it is good but at least it is working. Hope to see a better solution here XD – Zhou Zhi Hua Feb 08 '17 at 05:59
  • Glad to hear you are getting things working! I'm looking at some solutions that implement an array of arrays of the different component types. If I can figure out how to implement something like that I might post a solution here myself lol. – Jason Feb 08 '17 at 06:04

1 Answers1

2

Entities shouldn't know about your systems, they should be just a collection of components. Otherwise the process of introducing another engine system would require changing entity class as well, which defies the whole purpose of ECS.

Systems, too, should not manage components at all. One system may use several components and many systems may use, e.g. position/collision geometry components.

So, in my opinion:

  • Components, ideally, should be simple data-only classes, while all the processing is done within systems.
  • Entity must only provide a way of adding and removing components, and telling whether it has specific component.
  • Some sort of entity manager must store components in a cache-friendly way for systems to access them and should be able to provide a list of entities, that have specific set of components/tags to systems.

This way, for example, if you want to add scripted behavior for some entities, all you have to do is add ScriptComponent and ScriptingSystem. All of your existing code would not require any change.

This question has a lot of very useful resources on the topic.

Community
  • 1
  • 1
w1ck3dg0ph3r
  • 1,011
  • 6
  • 5
  • Okay, so your saying an Entity Manger class should be reponsible for handling all components of an Entity in the game? And that all systems (graphicsSystem, PhysicsSystem, ScriptingSystem) can use and swap components in and out as well? – Jason Feb 08 '17 at 06:26
  • @Jason It could be (and maybe better be) called something more descriptive, but not the systems themselves definitely. Systems would not, generally, add/remove components, your world/scene would. There is a lot of papers on ECS and some open-source implementations as well, you definitely should check them out. – w1ck3dg0ph3r Feb 08 '17 at 06:35
  • @Jason Also, there was a [nice talk on the implementation of ECS](https://www.youtube.com/watch?v=NTWSeQtHZ9M) at CppCon15 by Vittorio Romeo. – w1ck3dg0ph3r Feb 08 '17 at 06:43