Continuing a series of posts where I try to detail the past, present and maybe have a glimpse at some possibilities of where the Game Entity might evolve in the future.
There is a part of me that wishes I had actually written the entire series of posts for this article up front, it’s proving quite interesting writing about things that are supposed to fit together with future posts that haven’t been written yet. So please bear with me while your reading this, I’m hoping it will all make sense by the time we get to the end.
In order to keep things simple here I am going to put aside components for the moment and how they have changed the landscape of the Entity. Although a lot of what I am talking about here is still valid under a component system, I will take a look at the different component systems that I have encountered in my next post.
The Life Cycle
You are born and then you die, the bit in-between is called LIFE! Pretty much sums up most things, bumble bee’s, dolphins, developers, dragons and game entities. Here are the stages of life that most entities go through, this hasn’t really changed that much over time.
A blank slate, everything is cleared, default values set, pointers cleared to null.
I have encountered some architecture’s that have banned the use of Constructors and Destructors in game entities! Usually because of a misunderstanding of how C++ works and usually backed up by the fact that some engineers just can’t stop themselves from doing memory allocations and other nonsense in the constructor.
Usually passed into this stage is some kind of configuration data (usually loaded from the level) indicating how this entity should configure itself, for example its position in the world, physical properties, what visual assets to use, what audio assets to work with, how much health and so forth.
Once initialization of all entities has taken place this “second” initialization stage allows us to setup inter-entity relationships, sometimes we referred to this as the “First Frame Process”. For example a doors connection to the navigation system, an elevator to its trigger regions, Characters to possessions, etc.
This is entry point for where all the cool things happen, go crazy, have fun, make awesome things!
It’s surprising how often I have encountered an architecture that supports the Resolve stage but engineers have still implement something like this at the top of the Update function:
if ( m_FirstFrame )
m_FirstFrame = false;
// Do something interesting that I couldn’t do in the resolve stage.
The reasons for doing this comes down to a simple logic problem, Entity A can’t finish resolving itself until Entity B has resolved!
There are several ways in which this could be solved one method would be to introduce a processing priority so that Entity B is always processed before Entity A. Another method would be to split the Resolve stage into Pre-Resolve and Post-Resolve steps.
On over forty projects I have never seen either of these possible solutions implemented for two very good reasons first there is usually only one or two game entities that require this “Fix” (or “Hack”, depending upon your perspective ) and secondly even these specific fix’s have scenario’s where they too would not be a good solution.
The draw stage is called prior to rendering of the entity, usually to allow the entity to configure the renderer with the latest information.
It is at this point any assets associated with this entity are released and just to be clear this does not necessarily mean (and usually doesn’t) that the assets get removed from memory. Asset management is another whole interesting subject but not for this post.
Cleanup and prepare for deconstruction.
The de-constructor should really just be a check list to make sure that before the entity is deleted nothing has been left behind… i.e. something wasn’t correctly deinit. Even the simplest of checks in debug mode that scans the objects memory to make sure everything is zero is in-valuable at catching leaks when something has been forgotten.
The seven stages of a Game Entities life, a few systems have the additional pre / post functionality for the update and render stages but generally everything here will exist in most if not all systems being used today (I’m sure someone will correct me if this statement is wrong ).
How we manage our entities can have a huge impact upon the CPU and this is always an area that can be tailored to the specific game genre for optimal performance. Below I have detailed some of the common core processing systems that I have used in the past.
Basic frame Processing
Usually this is the first implementation of an entity system that we write when we are first learning how to write games, it’s quick, it’s dirty, it’s simple and you would be surprised by how many games that are published still even today using this as their processing architecture. Not that there is anything wrong with this, if you have less than a couple hundred objects and are not trying to push any limits then you don’t need to do anything more complicated.
The game loop looks pretty much like this:
The biggest problem with this is that it locks the render and update stages into sync with each other. If you wanted to maintain 60fps in your game this would mean that you had to update every entity and render them all in 1/60th of a second. A couple of hundred entities you might be fine with, however if you have several thousand objects, you have a problem, even if half of those objects are invisible (i.e. triggers, markers, barriers).
Time splice processing
Time splicing has been used to great effect on a number of games essentially it spreads the processing over a number of frames. The game loop would look something like this:
Update 25% of entities
This essentially means that the game update is running at ¼ of the speed of rendering, with 60fps rendering that would be 15fps update. A variation to this system is to specify how much CPU time is available for processing each frame the system would then start processing entities until it ran out of time then would pause until the next frame.
It is worth mentioning that this processing system and the following systems are not possible if you do not have a rendering system that is capable of running independently of the game entity update. By this I mean it must be capable of interpolating position, rotation, animation, etc between the entity updates.
Variable frame processing
Not every game entity needs to run at the same speed, for example the player we might want to run at 60fps but do we really need that magical door that fires fireballs at the player to also run at 60fps, probably not it could run at 10fps with no issues. Variable frame processing allows you to indicate on each game entity just how fast it should update.
One major issue to watch out for when using this processing system is that it needs to auto balance itself! Let’s say we gave all game entities an update of 20fps… it would be rather pointless if they all triggered at the same time on the same frame that really would make a lovely spike in the CPU graph.
Just to give you a sense of how powerful and useful this can be at spreading the entity processing load, the imps in Dungeon Keeper 2 were being processed at 4fps.
Level of detail processing
LOD processing allows the game entity to dynamically calculate its own fps based upon how far away it is from the focus of attention (usually the cameras position). For example a bird flying 500 meters away might only need to be updated at 1 fps unless it happens to be within 50 meters of the camera in which case it would ramp up as it got closer to say a maximum of 20fps.
Obviously this method doesn’t work particularly well if all the game objects are clustered together in a small area.
Scene management isn’t just for rendering it can be used quite dramatically to control CPU usage, especially when combined with variable frame processing. How you decided to manage your scene can also make a huge difference, an octree, visual cells, rooms, zones, arenas, there are plenty of options.
For all these different methods of processing game entities I have never seen a priority system implemented, in fact the closest I have seen to an implementation would simply be to switch two entities round in the update link list. Effective I suppose but extremely clunky.
One of the things Nicolas MERCIER commented about last post was multi-threading the entity processing. I have never written a game that has used multiple-threads for processing, I have never heard of any game that has used it either. It obviously makes a lot of sense. However there is something niggling at the back of my mind that makes me think there are some serious issues with this. But the short end of it is that I haven’t had the time to run any experiments. Has anyone out there got their entities being processed under multiple-threads? If so what issues have you encountered?
By the way Nicolas, I’m still planning on returning to your comments towards the end of the article around part V or VI.
Next blog I am going to talk about the current state of components and how it has evolved and changed the landscape of the game entities.
The Game Entity – Part III, Components
The Game Entity – Part IV, Game A.I.