1
\$\begingroup\$

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 a Renderable 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 produce Renderables, but Renderer 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 the Position 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

\$\endgroup\$

1 Answer 1

7
\$\begingroup\$

If anything, the first option might be better for cache misses since generally you'll be iterating through, say, all the Renderable components at once. Just copy the data you need into that component to avoid cache misses due to looking up data.

But it seems like you're suffering from design paralysis. Do you actually have a working game yet? Are the problems you're trying to solve actual problems given the scope of game (or games) you're planning on using with this tech as well as the target platforms you're hitting?

Just pick something and move forward. Benchmark if you really need to care about performance (chances are you don't). Use good design practices to keep things separated enough that you can refactor into one or the other pattern if the need arises.

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .