I'm stitching together the workings of a component based game engine, and as such have been deeply reading into many aspects of both game engine architecture and a fair amount of opinionated theory of different programming styles / do's and dont's. Etc.
Currently, I really like the idea of treating components like little data structures and having larger sub-systems handle this data appropriately. Thus the "GameObject" is more of a GUID that ties in these struct-based components into a loosely defined object with various properties.
So my question, or well current delima is how to store these various components and I seem to have two competing ideas.
The easy way to handle storing these components, is to have each sub-system double as a factory class which creates and stores the component into a hash table which the sub-system maintains. So the
Renderer
would have a method that could produce and store aRenderable
component given a GUID and some input parameters. Whenever a object or object component is removed from game each sub-system could be messaged and that sub-system could then delete the corresponding component without trouble.In addition to that, components of the same type are grouped together and since these components are all the same size this makes for a pretty damn clean memory management. I see no problem using std::vector or a hash table of some sort to contain these elements.
The issue I have with this approach is that it fragments a (all) "GameObject's" significantly. Suddenly the position component of a given object is located miles away from the physical component. This seems like a performance nightmare, looking up any other component becomes a cache-miss, etc. Which brings me to option #2...
The other approach I've come up with is to keep the factory part of the sub-systems.
Renderer
would still produceRenderables
, butRenderer
would not be responsible for storing the component, instead it would be given a location to write the component struct to as an input parameter by a dedicated system, like a memory manager.The advantage here is components belonging to a particular GUID could be grouped together in contiguous memory (at least in theory), providing a chance that the needed date for another component (say
Physical
wants to alter thePosition
component) may already exist in the processors cache due to the effects of cache-lines.The (massive) disadvantage that I see in doing this is managing the necessary memory to group these differently sized components together, that sounds like a nightmare to me.
So what I wish to ask is, what do you guys think? Is there a really smart third option I haven't thought of, or am I crazy for even caring about cache-misses? In that case, is the easy way just the correct way, etc, etc.
Thanks, -Cody