[In this reprinted #altdevblogaday in-depth piece, former KmmGames senior game programmer Michael Carr-Robb-John explains component granularity and how it can be useful in improving code.]
In one of my previous post (The Game Entity - Part III, Components
), I touched on the subject of component granularity as being something to keep an eye on. Since the post, I have had a few discussions where there has been some confusion about what is meant by component granularity.
Over the years a number of very intelligent people have tried to create a quantitative system for granularity with varying degrees of success. As one chap put it :
"Granularity is a bit like pornography, it's hard to define but you know it when you see it."
I have had a fair bit of experience with components and thought it would be interesting to try and explain my perspective and thoughts on the subject. Hopefully clarifying what is meant by component granularity and how it can be useful in improving the code.
"Granularity is an indicator of how much functionality is being encapsulated inside a single component"
How I gauge a component's granularity is based upon it's functionality, this is NOT based upon the number of functions or the amount of data contained within the component. I generally describe a components granularity size with words such as; Tiny, Small, Medium, Large or Huge.
Let's consider two components; The first is called "Health", it can handle different types of damage, keep track of poisons, damage resistances and generate messages when certain conditions are met. In short it is the bee's knees and contains a fair number of functions and data in order to allow it to work.
"Basic Health," on the other hand, knows nothing of the different types of damage that exist, doesn't generate any messages, and is as the name says basic.
Both of these components I would personally consider to have a similar granularity of between small to medium.
The granularity alarm
Let's be clear, there is nothing wrong with a component rated with a large or tiny granularity. There are games that have shipped with both examples and they work just fine. The granularity however can be an indicator that there might be something with the design of your component that could be improved.
Every entity component system has a certain overhead in terms of memory and CPU cycles to handle and process each component. If your component falls into the tiny range, then very likely you are spending more on the maintenance of the component than you are on the actual component itself.
An example of this might be a component that contains a single floating point value, during the update stage it simply adds the current time delta to the float. In this scenario, I would suggest that this functionality would be better integrated into other components since it doesn't do enough to justify the overhead cost.
The larger the granularity size, the less likely the component is to be re-usable and / or interchangeable. One of the first things that people new to components do is usually take the code from an entire entity and simply dump it into a component. If you have an entity with a single component attached, that's a good indicator that something on the design side might not be right.
The subject of component design could fill a few posts, however it actually can be boiled down to a simple sentence:
"The high level aspirations for all component design should be to contain a chunk of functionality that is self contained, re-usable and interchangeable."
To clarify that a little:
A chunk of functionality - Well that's the granularity that is so interesting to pin down.
Self contained - Although it might use other components to make decisions / achieve results it doesn't actually need any other component to do its job. For example, Health and Navigation components.
Re-usable - The whole point of a component system is to allow as much functionality to be re-used as possible with minimal effort. The higher up the component chain you go the less re-usable parts become, for example the Dragons Brain is specific to the dragon and won't be very re-usable except on other dragons. The components Render, Physics, and Audio however are incredibly re-usable.
Interchangeable - This is probably the most difficult aspiration to attain, a component that can be swapped in and out with little modification. An example is the Physics component, I have worked on projects where the physics system has been switched two or three times during development. On one of those projects, we were not using a component system, and hence the game code needed some extensive rewiring with each switch rather than a single component's internals.
Component Granularity is a very fuzzy subject, hopefully his has helped to clarify some of the confusion.
[This piece was reprinted from #AltDevBlogADay, a shared blog initiative started by @mike_acton devoted to giving game developers of all disciplines a place to motivate each other to write regularly about their personal game development passions.]