Components

Dear Rebecca from last week – you have been programming with Unity and C# for too long and it shows:

I will add a Cleanup function to all Screens so that I can call it before I delete the Screen itself in the main loop.

Uh – that would be known as a destructor. How embarrassing. Anyway, I’ve now added a virtual destructor to the Screen class and overloaded it for any Screens where I was creating memory.

After reading over my other idea from last week:

I also thought it would be a good idea to have some sort of list of Sprites and Texts in the base Screen class.

I think doing that is actually a bit of a waste of time – since some of my Sprites are now hidden within my messy “Player” and “Enemy” classes. I originally wanted to try the Component pattern out on a fresh project – but I might as well give it a go now, especially since I have some classes that would make more sense in this pattern.

To switch to the Component pattern I’ve been referencing the great book Game Programming Patterns by Robert Nystrom. I actually paid for it because it’s helped me so much – but you can also access it for free (legally) here.

Anyway – setting this up is going to take more than one session, so I’ve made another branch for this feature just to make sure I don’t destroy the working game I already had. You can find that branch here if you’d like to have a look at what I’m up to.

I decided to have an abstract Component class which all my components are going to inherit from. To begin with my class looked like this:

class Component {
public:
 virtual void Update() = 0;
private:
};

The other class is a GameObject class (yes, my time with Unity is really rubbing off). I wanted the GameObject to have a collection of Component pointers – then I can add to and remove from this collection if needed. To start with:

class GameObject {
public:
 ~GameObject();
 void AddComponent(Component* a_component);
 void Update();
private:
 std::vector<Component*> m_components;
};

Right now I’m making the assumption that I will only have one Component of each type in a GameObject. So, if I have a Sprite component – I can only have 1 Sprite within a GameObject. Currently there’s no safeguard for this – I’ll have to do this in the future.

Once I got up to the RemoveComponent function in GameObject I got a tad stuck (actually, I spent a good twenty minutes trying to get out of the C# mindset I usually work in – with reflection this solution looks a bit different). I want to be able to remove a Component by type since I’m not likely to have a pointer to the exact Component  that I want to delete. Which means I need to have some way of determining the type of Component at runtime.

I’m not super happy with the solution I’ve rested on for now, but perhaps I can revisit it once I’ve learned more and make it better. I decided to add a type variable to Component that should make identifying it a bit easier.

enum ComponentTypes {
 RENDERER,
 PHYSICS,
};

class Component {
public:
 virtual void Update() = 0;
 ComponentTypes GetComponentType() { return m_componentType; }
private:
 ComponentTypes m_componentType;
};

The reason I am a bit dubious about this is because I will have to add a field to this enum each time I add a new Component child class. It seems like it would be easy to forget to do this, which could cause bugs. Having some way where a Component child class could register itself as a type somehow would be good – will have to think more on this.

Anyway, it’s now a lot easier to make a RemoveComponent function – I just need to pass it a type and loop through looking for that type.

void GameObject::RemoveComponent(ComponentTypes a_type)
{
   int indexToErase;

   for (int i = 0; i < m_components.size(); i++) {
     if (m_components[i]->GetComponentType() == a_type) {
       indexToErase = i;
       break;
     }
   }

   m_components.erase(m_components.begin() + indexToErase);
}

This could definitely be done better. I want to take performance into account a little bit – so I would like to find out:

  1. Is a vector the correct data structure for this? (I know vectors perform well for iteration, but slowly for removals + resizing. I am doing a lot of iteration though…)
  2. Should I be using this vector? Should I roll my own? Or should I try using the EASTL since they’ve just released it? (I’m leaning towards the last option since I’d learn quite a bit from that experience).

I also added a GetComponent function to the GameObject – mostly because Unity has one and I use that all the time, so it seemed like a good idea. It’s really the same as the remove function – I just loop through until I find a component of the correct type and return it.

Right, quite happy with my progress for tonight – next time I will try and adapt my Sprite class into a Component, which may get ugly :p

If you have any questions or suggestions then please let me know – pretty sure the comments here work, if not then feel free to tweet at me: @chainedchaos31

Advertisements

8 thoughts on “Components

  1. Hey Rebecca,
    I have a couple of suggestions. Instead of keeping all your components in one vector, keep a vector for each component type. That way you can easily iterate over all the components of a given type. This is useful for doing things like physics updates: you can then iterate over all the physics components without touching your GameObjects. It also reduces the search time for finding a given component.

    A vector is fine for what you’re doing. I would make sure to preallocate the vector through and I would also keep a pool of components that I allocate from (rather than using heap memory). This helps with performance as when you do iterate over a vector of components you are the stepping through memory in order which is more cache friendly that chasing pointers (You could use vector and let the vector manage the memory for you, or stick with the Vector and make sure to keep your components in order in another pool)

    Regarding vector performance, I wouldn’t worry too much just yet. It is only slow when it has to resize, so make sure that you rarely do that.

    -Tony

    Liked by 2 people

    1. “Instead of keeping all your components in one vector, keep a vector for each component type”

      This is probably one of the best decisions I made with my own component system. I still store them on my entities (GameObjects in Unity terms) for convenience, but centrally in the scene there are vectors per type for the updating work. Also means I don’t have to walk on egg shells wondering if components are updated in the correct order vs other component types, since you can always guarantee, for example, Animation components are always updated before Model components.

      Liked by 1 person

      1. Right, so ideally I’m creating pools of each component type in the scene (which is where I can update them) – then I just store pointers to this in each GameObject.

        Unity has a loooot of different components though – this setup potentially leaves us with a lot of pools and vectors, right? Or am I aiming to have a few generic base types with all the variables that could be used by any of the children (so that all the Physics objects are the same size)?

        Liked by 1 person

  2. Hi,

    There’s no need to add m_ComponentType. You can do it, but C++ has a mechanism to determine the type of a pointer at runtime (RTTI)
    One way to do it would be:
    RenderComponent* r = dynamic_cast(component);
    if(r) //r will be null if component is not RenderComponent
    {do stuff with r}

    Or you can use the newer typeid(something).

    Regarding the last questions:
    Vector insert is not slower than list insert for “almost” all cases that you can think about.
    You can test it yourself here with different element sizes (and microsoft’s vector has a perf bug but it’s still way faster).
    https://github.com/AlexEne/Presentations-2016/blob/master/Memory/list_vs_vector.cpp

    Roll your own after you profile and see that it’s the bottleneck, otherwise it doesn’t matter :).

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s