0

My goal here is to create a unique ID (starting a 0) for each child of a specific class. I'm not sure if it is possible in the way i want, but i figured i'd ask here as a last resort.

Some context:

I'm creating my own 2D game engine and i want it to have an ECS as it's back bone (Before anyone says anything, i'm doing this as a learning experience, i know i could just use an already existing game engine). My idea is that each class that implements the 'EntityComponent' class should have a unique ID applied to it. This needs to be per child, not per object. I want to use this ID as the index for an array to find the component of an entity. The actual ID that each Component gets is unimportant and each component does not need to be assigned the ID every run time.

My hope is there is some way to create something similar to a static variable per class (That implements the Entity Component class). It needs to be quick to get this value so doing an unordered_map lookup is slower than i would like. One thing i do not want to do is setting the ID for every component myself. This could cause problems once many components are made and could cause problems if i forget to set it or set two components to the same ID.

One idea i had was to make a variable in EntityComponent called ID (And a getter to get it). When the entity is constructed it looks up an unordered map (which was made at run time, assigning an ID to each class) for what ID it should have. The price of looking up once at construction is fine. The only problem i see with this is there is a lot of redundant data (Though overall it seems it would account to a pretty small amount). With this, every single transform component would have to store that it its ID is x. This means potentially thousands upon thousands of transform components are storing this ID value, when only 1 really needs to.

Basically i am after an extremely quick way to find an ID for a class TYPE. This can be through a lookup, but it needs to be a quick lookup. I would like something faster than unordered_map if possible. If this can be done through compile time tricks (Maybe enums?) or maybe even templates i would love to hear your ideas. I know premature optimisation is the bad, but being able to get a component fast is a pretty big thing.

What i'm asking might very well be impossible. Just thought i'd ask here to make sure first. I should also note i'm trying to avoid implementation of this in the children classes. I'd like to not have to set up the same code for each child class to create an id.

Thank you.

Lolop
  • 67
  • 10

3 Answers3

0

In order to get something corresponding to the actual type of an object, it either needs to be in the object itself or accessed via a virtual function. Otherwise the type will be determined by the type of the variable it is associated with.

A common option when speed and size are both important is to have an integer identifier associated with each type (when the full type list is known at compile time) and use that integer value in a specific way when you want to do something based on the type.

The integer mechanism usually uses an enum for generating the corresponding value for each type and has that field in every object.

The virtual method variety, I've used boost::uuid and a static data member in each class and a virtual method get'er for it.

xaxxon
  • 19,189
  • 5
  • 50
  • 80
  • Whoops didn't meant to press enter. I was going to ask about your integer identifier comment. Do you have any links to an example to see if i could use that? My goal is to not require extra steps to creating a EntityComponent. I want to create a new class the inherits from it, and everything else automatically happens. If there is a way to create an enum at compile time, that would be perfect i think. – Lolop Oct 18 '16 at 02:44
  • 1
    @Lolop unfortunately the examples I know of are terribly complicated (and I don't completely understand them) -- clang and v8 both use this system for a pseudo RTTI system, but there are multiple levels of macros to organize everything. the simpler version is to just have a enum ClassId {CLASS_ONE, CLASS_TWO, CLASS_THREE} and have a ClassId class_id = CLASS_; in each of your classes. – xaxxon Oct 18 '16 at 02:56
  • Unfortunately i was going to do something similar to Unity and have C# as the scripting language for my game (I wanted to learn C++/CLI). I think this means that using defines is not a possibility as i don't want to have to modify the game engine every time i make a new C# component (The idea is to keep them separate). – Lolop Oct 18 '16 at 03:04
  • unity doesn't use c# as a scripting language -- it uses C# as it's only language. At least from what I understand. – xaxxon Oct 18 '16 at 03:08
  • I'm thinking the idea that wrote in my original post will do fine for now. This post was sort of just to see if there was anything better. Sure it has redundant data, but would only be an extra 16 bits (1 short) per component. It might add up to a few megabytes if i have hundreds of thousands of components, but overall i think it's negligible. I'd prefer speed over memory. – Lolop Oct 18 '16 at 03:10
  • Unity uses C++ for the game engine. The C# Scripts interface with the game engine through C++/CLI. – Lolop Oct 18 '16 at 03:11
  • Hrm, I guess I don't quite understand what's going on in unity, but regardless, the options i listed above are pretty much the choices available. You either do something at compile time or you do virtual method dispatch at runtime. – xaxxon Oct 18 '16 at 03:15
  • Thank you. I thought that might be the case. What i'm going to do is basically the virtual method, except i store the value in a member variable. Like i said this uses more memory, but means there is less repeated implementation and it's also less work when creating new components. – Lolop Oct 18 '16 at 04:36
  • @Lolop not sure how it's less work. You still have to define the value for the class somehow. – xaxxon Oct 18 '16 at 05:26
  • I create a member variable in the base class (EntityComponent). This means that each individual object of type EntityComponent stores the ID of that particular component. My idea is to create an unorderedMap which will map from class name to ID value. This map will be created when the engine starts. This means whenever a new component is constructed (inside the base class constructor), it will look up this map and save it to the MEMBER variable (Not static). – Lolop Oct 18 '16 at 07:30
  • " My idea is to create an unorderedMap which will map from class name to ID value" that requires work whevner you create a new component type, right? – xaxxon Oct 18 '16 at 07:31
  • And just as i type that i realise that it wont work how i want it. I forgot that i would have liked to be able to say "GetComponent" which using member variables for the ID wouldn't work. I think i found a solution though using templates. [The second answer here talks about Curiously recurring template pattern](http://stackoverflow.com/questions/1390913/are-static-variables-in-a-base-class-shared-by-all-derived-classes). This looks to give a separate static variable for each child class, which is what i wanted. – Lolop Oct 18 '16 at 07:32
  • Yes it would have required work when it was constructed, but that's a once off thing per component. I could be calling get component hundreds - thousands of times per frame (In a bad situation). So a once off per object is not as bad as doing it many times per frame. – Lolop Oct 18 '16 at 07:34
0

Declare a virtual function newId() in EntityComponent. Implement this function to get and increment a static variable in each class, which children you want to have a unique Id. Assign Id in the constructor: mId = newId();

sanzinim
  • 1
  • 1
  • This would require me to make a static variable in each child class right? So Transform would need its own static 'mID' variable, and i'd also have to make a static 'mID' variable for say a health component? I would like to avoid this if i could. I'd like to keep all this ID stuff away from the children classes and have them be assigned a value, rather than them getting their own value. This might not be possible but i thought i'd ask just in case – Lolop Oct 18 '16 at 02:58
  • now I understand. Not each object of child class has unique Id, but each child class. Are you not satisfied with operator `typeid`? You can get a class name for exmple, and use it as Id. – sanzinim Oct 18 '16 at 03:27
  • Am i able to force TypeID to start at 0 and go up in 1's? I am using this for an array index, so i need it to be 1 - x values in increments. Doing lookups is a bit too slow for what i wanted, so having any kind of map doesn't work for me. – Lolop Oct 18 '16 at 04:34
0

don't know this if this is what you meant and i know this is an old post however this is how im currently dealing with a similar issue, maybe it will help someone else. (Im also doing this as a learning experience for uni :) )

in the controlling class or its own utility class:

enum class EntityType{ TYPE_ONE = 0, TYPE_TWO =1};

in class header:

#include "EntityType.h"
class Whatever{
public:

  inline void getType(){return _type;}
OR
  inline void getType(){return EntityType::TYPE_ONE;}

private:
  EntityType _type = EntityType::TYPE_ONE;

};

Hope this is helpful to anyone :)