To pool game entities or to use an update loop
To pool game entities or to use an update loop
Every entity in my game is derived from the CEntity class, and my question is how I should update the entities.
1. My first technique holds all the entities in a vector and every frame the entity vector is iterated through and every entity is updated via a function being called. I can see some odd updating conflicts like when one entity sends an already updated entity a message. Messaging seems odd this way too, as I don't know where to process it.
2. The second technique stores or pools all the entities in a map with an ID for a key. Then the only way to update an object is to send it a message. Each message isn't queued and looped through, but send directly to the entity and processed then. Any entity that requires updating on every next frame tick, will be sent a message.
I would just appreciate some advice on this subject. Maybe prior experience using both methods, pro's and con's for both, that sorta thing. I suppose it's also based on what kinda game I'm making too. It's going to be an action/adventure, Zelda style game, so it'll have moderate entity quantities but nothing extreme (like, say, an RTS) at any one time.
1. My first technique holds all the entities in a vector and every frame the entity vector is iterated through and every entity is updated via a function being called. I can see some odd updating conflicts like when one entity sends an already updated entity a message. Messaging seems odd this way too, as I don't know where to process it.
2. The second technique stores or pools all the entities in a map with an ID for a key. Then the only way to update an object is to send it a message. Each message isn't queued and looped through, but send directly to the entity and processed then. Any entity that requires updating on every next frame tick, will be sent a message.
I would just appreciate some advice on this subject. Maybe prior experience using both methods, pro's and con's for both, that sorta thing. I suppose it's also based on what kinda game I'm making too. It's going to be an action/adventure, Zelda style game, so it'll have moderate entity quantities but nothing extreme (like, say, an RTS) at any one time.
Ride the Spiral Development:
spiralride.blogspot.com
spiralride.blogspot.com
I have usually a whole bunch of update functions which are outside the entities and just modify game entities with whatever methods necessary.
So I might have for example an UpdatePhysics which will loop all entities and call setPosition for the Nodes. This is usually called every physic tick (which might be less or more often than rendering updates). I might have an UpdateNetwork which will only update certain objects which are maybe defined by an object ID.
If the object really need to do something, for example on each physic update , then I add additional functions for that which are very often called OnPrePhysicUpdate and OnPostPhysicUpdate (I tend to need both).
My point is that I start the other way round. I don't add interfaces to my object until I really need them. Which interfaces are needed depends on the game. I start with the update functions I need, which are generally outside the entity class. But that does not prevent me to add update and message functions whenever I need them to the entities.
So I might have for example an UpdatePhysics which will loop all entities and call setPosition for the Nodes. This is usually called every physic tick (which might be less or more often than rendering updates). I might have an UpdateNetwork which will only update certain objects which are maybe defined by an object ID.
If the object really need to do something, for example on each physic update , then I add additional functions for that which are very often called OnPrePhysicUpdate and OnPostPhysicUpdate (I tend to need both).
My point is that I start the other way round. I don't add interfaces to my object until I really need them. Which interfaces are needed depends on the game. I start with the update functions I need, which are generally outside the entity class. But that does not prevent me to add update and message functions whenever I need them to the entities.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
How you do it is really going to be based on your particular game's needs.
Here are some questions that might help you decide:
1) does every object need to be 'updated' every frame?
2) how many messages are sent/received per object per frame?
3) do you have lots of objects (>500?) which do many small operations, or only a few objects that do lots of operations?
As a matter of experience: typically I will keep my objects in several different arrays (one for enemies, one for dumb level objects, one temporary entities like projectiles) and go thru and update each of those arrays every loop.
I use a static array if the number of objects fluctuates a LOT (ie: memory pool) or if it doesnt flucuate at ALL (ie: there are always exactly 4 of some type), and a resizable vector otherwise.
Typically I have several seperate message queues and let objects register with the queues they want to listen to; then in my update loop (before I update my objects) I trigger my message que to send its message to each of its listeners. With a little planning you wont have any conflicts when objects receive similar messages.
Here are some questions that might help you decide:
1) does every object need to be 'updated' every frame?
2) how many messages are sent/received per object per frame?
3) do you have lots of objects (>500?) which do many small operations, or only a few objects that do lots of operations?
As a matter of experience: typically I will keep my objects in several different arrays (one for enemies, one for dumb level objects, one temporary entities like projectiles) and go thru and update each of those arrays every loop.
I use a static array if the number of objects fluctuates a LOT (ie: memory pool) or if it doesnt flucuate at ALL (ie: there are always exactly 4 of some type), and a resizable vector otherwise.
Typically I have several seperate message queues and let objects register with the queues they want to listen to; then in my update loop (before I update my objects) I trigger my message que to send its message to each of its listeners. With a little planning you wont have any conflicts when objects receive similar messages.
a screen cap is worth 0x100000 DWORDS
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Re: To pool game entities or to use an update loop
I consider messaging to be overkill for most games, if for no other reason than it makes it unnecessarily complicated to debug.
Messaging implies that every object needs a message queue and that they need to process those messages asynchronously, or that there's some benefit to wrapping events in a generic message wrapper and having them sent via a generic method that then unwraps them and acts on the contents.
Bollocks, IME. Unless you have a compelling reason to defer acting on events, then just call a specific method directly and implement the event synchronously. 'Synchronously' may involve setting a state which causes further action later, e.g. your input or network manager tells a spaceship to turn its engines on, which sets the engine state, but you don't action the move until the main process loop. But send it via a specific method and capture it in an explicit state in your object, rather than as a generic message on a queue. Wrapping and unwrapping of messages adds nothing, and just obfuscates what's actually going on, for the slim benefit of reducing your methods from "doThis()" and "doThat()" to a generic "handleMessage()"
I agree with keless about partitioning objects by their level of activity, although calling a NOOP process() method on even thousands of objects per frame probably isn't going to kill your frame rate. Note that if you choose to use a messaging design, then you have to process all objects every frame in order to check their message queues.
IMO messaging is an appropriate idiom for a generic system design, not a game implementation, although as always there will be exceptions, for engines or extensible games. But if you're writing a game, pffft, your design is best expressed through explicit methods and synchronous execution.
Messaging implies that every object needs a message queue and that they need to process those messages asynchronously, or that there's some benefit to wrapping events in a generic message wrapper and having them sent via a generic method that then unwraps them and acts on the contents.
Bollocks, IME. Unless you have a compelling reason to defer acting on events, then just call a specific method directly and implement the event synchronously. 'Synchronously' may involve setting a state which causes further action later, e.g. your input or network manager tells a spaceship to turn its engines on, which sets the engine state, but you don't action the move until the main process loop. But send it via a specific method and capture it in an explicit state in your object, rather than as a generic message on a queue. Wrapping and unwrapping of messages adds nothing, and just obfuscates what's actually going on, for the slim benefit of reducing your methods from "doThis()" and "doThat()" to a generic "handleMessage()"
I agree with keless about partitioning objects by their level of activity, although calling a NOOP process() method on even thousands of objects per frame probably isn't going to kill your frame rate. Note that if you choose to use a messaging design, then you have to process all objects every frame in order to check their message queues.
IMO messaging is an appropriate idiom for a generic system design, not a game implementation, although as always there will be exceptions, for engines or extensible games. But if you're writing a game, pffft, your design is best expressed through explicit methods and synchronous execution.
Last edited by rogerborg on Tue Jan 15, 2008 2:41 pm, edited 2 times in total.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
I use to the rogerborg technique.
I have some collection(the implementation of this (hash, list,etc) is up to you) for "kind" of object.
My game loop looks this way:
Physic anyway will update accordint some frame (this is implicit inside).
IA will update only for the ones which have IA (you can have it in separate ti collections or not (if no, the only loose in performance will be and "if" statment or a call to function with nothing to do (maybe a little more heavy).
I have already test this way in 2d games and works perfectly, And now I am trying for 3d game (fine until know), anyway I think it should not has so much differences.
And I need to add the "GAME STATE" controller/manager, wich I think will be add some hoow before graphyc, I have not test it this.
Until know I have had only a little conflict between order action, but nothing importan and easy to solve.
By the way rogerborg, what do you mean wit "IMO" thechnique? English is not may native tongue.
I have some collection(the implementation of this (hash, list,etc) is up to you) for "kind" of object.
My game loop looks this way:
Code: Select all
while(mG->run()) {
if(motorGrafico->isVentanaActiva()) {
physicMotor->update(); //pHYSICS
actorManager->updateAI();//Artificial Inteligence
actorManager->update(); //The rest update which don't get into the rest
controllerManager->update();//Update for controller user actions
motorGrafico->updateBegin(); // Graphic part (renderin 3d
gui->updateGraphics(); // some gui stafff
motorGrafico->updateEnd(); //
}//isWindowActive
}//while
IA will update only for the ones which have IA (you can have it in separate ti collections or not (if no, the only loose in performance will be and "if" statment or a call to function with nothing to do (maybe a little more heavy).
I have already test this way in 2d games and works perfectly, And now I am trying for 3d game (fine until know), anyway I think it should not has so much differences.
And I need to add the "GAME STATE" controller/manager, wich I think will be add some hoow before graphyc, I have not test it this.
Until know I have had only a little conflict between order action, but nothing importan and easy to solve.
By the way rogerborg, what do you mean wit "IMO" thechnique? English is not may native tongue.
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
IME - In My Experience
IM[H]O - In My [Humble] Opinion
HHOK-IR60MPTBTG - Ha Ha Only Kidding. I'm Really a 60-year-old Man Pretending To Be A Teenage Girl
IM[H]O - In My [Humble] Opinion
HHOK-IR60MPTBTG - Ha Ha Only Kidding. I'm Really a 60-year-old Man Pretending To Be A Teenage Girl
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
.rogerborg wrote:IME - In My Experience
IM[H]O - In My [Humble] Opinion
HHOK-IR60MPTBTG - Ha Ha Only Kidding. I'm Really a 60-year-old Man Pretending To Be A Teenage Girl
But by the way I re-read your post and the other ones above, when you mean "messagin" do you mean like collaboration diagram messagin?
if so, then I do use that but mixed with what above have discribed.
Or do you mean messaing like assincronic messagin to "mail boxex" and so on?
Thats actually the opposite of what a good messaging system is used for.Messaging implies that every object needs a message queue and that they need to process those messages asynchronously, or that there's some benefit to wrapping events in a generic message wrapper and having them sent via a generic method that then unwraps them and acts on the contents.
If you'll recall my statement about messaging queues and listeners that register with those queues-- this allows you to push messages only to objects that need to hear them. Which means you can send signals to objects without a) sending to every object in a vector, and b) without those objects having to constantly poll for signals. This cuts down on processing a lot.
Furthermore messaging helps keep your code modular by allowing for a high-level communication between systems. For instance; you've got physics code that detects collisions between objects, and you've got AI code that needs to know when the user steps on a trigger object. A messaginq system can be the layer between the two that lets those systems act without having to get into each others' business.
Finally, a message queue done right makes debugging easier: simply log messages to a file and you can typically realize from a high level if things are going wrong. ie: "wtf, why is the door recieving move forward commands from the user input controller? oh.. cause I was using the wrong entity index over here"
a screen cap is worth 0x100000 DWORDS
Every technique is used - which one to use is part of the design of your code. Doing a design is one of those task which make up the programmers job and often more timeconsuming than typing the code :-) Just think through which advantages and disadvantages each technique has in your project and decide for the one which seems to work best.
I tend to agree with Rogerborg somewhat as I also see message systems as overkill for most games. I think with hard-to-debug he refers to the problem that you have no longer a callstack to trace on problems. And this can make finding bugs in the messagesystem indeed very hard. But certainly they are very useful in large projects as they are very flexible. So in most larger games you will most likely find a message system.
I tend to agree with Rogerborg somewhat as I also see message systems as overkill for most games. I think with hard-to-debug he refers to the problem that you have no longer a callstack to trace on problems. And this can make finding bugs in the messagesystem indeed very hard. But certainly they are very useful in large projects as they are very flexible. So in most larger games you will most likely find a message system.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
As CuteAlien points out, message queues are best suited to large scale games. The cell phone games I make at work don't use them at all.
The best example of a good use of a message queue is for AI and high-level game logic.
For instance; if your game has doors that automatically open when someone stands in front of them, you need to link the physics event of a player colliding with an bounding box in front of the door, with the actual motion of opening the door. In this very simple example, you COULD code a door object which has both physics hooks and game logic embedded into it that can poll the physics simulation (or wait for a collision callback, depending on your API) and gather that information for itself. This is naive programming.
A more robust solution would be to have three pieces: 1) physics, 2) door entity, 3) game logic controller. The physics realizes a collision between a player and a trigger bounding box, and writes a message to the appropriate queue. The game logic controller reads that message and tells the door to open.
How is that any better, you ask? It sounds a lot more complicated. Consider this: after completing this, your game designer states that there should be a button that opens ALL doors at the same time (or you should be able to trigger doors with remote panels, or AI's should be able to open doors without being near them). If you did it the first (simple/naive) way, you now have a lot of re-writing to do. If you did it the second (robust) way, you only have to send a message from the new events to the door.
Again, it comes to a question of scale and time. If simple and naive works for you, its certainly faster to write and usually less overhead. If you're laying ground on a serious project, robust is usually the way to go.
The best example of a good use of a message queue is for AI and high-level game logic.
For instance; if your game has doors that automatically open when someone stands in front of them, you need to link the physics event of a player colliding with an bounding box in front of the door, with the actual motion of opening the door. In this very simple example, you COULD code a door object which has both physics hooks and game logic embedded into it that can poll the physics simulation (or wait for a collision callback, depending on your API) and gather that information for itself. This is naive programming.
A more robust solution would be to have three pieces: 1) physics, 2) door entity, 3) game logic controller. The physics realizes a collision between a player and a trigger bounding box, and writes a message to the appropriate queue. The game logic controller reads that message and tells the door to open.
How is that any better, you ask? It sounds a lot more complicated. Consider this: after completing this, your game designer states that there should be a button that opens ALL doors at the same time (or you should be able to trigger doors with remote panels, or AI's should be able to open doors without being near them). If you did it the first (simple/naive) way, you now have a lot of re-writing to do. If you did it the second (robust) way, you only have to send a message from the new events to the door.
Again, it comes to a question of scale and time. If simple and naive works for you, its certainly faster to write and usually less overhead. If you're laying ground on a serious project, robust is usually the way to go.
a screen cap is worth 0x100000 DWORDS
I think am doing what you saing but in a differnt way, implicit way or someghint else, but in your example I don't need re-writeing nothing.
This is what I do:
door as an entity of type "Actor" must implement a function called "doAction(Action)".
for open:
I add the "open" action to the door.
and in the "doAction()" function of the door a implement what to do IN CASE of Action= "open". Could it came "close", "blow" etc.
If want to open on closer conctac just check in the "updateIA" or "update" functions for events to happen. Then just take the door and say door->doAction("open").
if want it to open on remote sing, then the same.... look for the event, if event happen then
door->doAction("open") nothing rewriten (only the new event OF COURSE).
is is what I doing a "message system" disign?
I realy ask, maybe it is ,but I did not realized it.
This is what I do:
door as an entity of type "Actor" must implement a function called "doAction(Action)".
for open:
I add the "open" action to the door.
and in the "doAction()" function of the door a implement what to do IN CASE of Action= "open". Could it came "close", "blow" etc.
If want to open on closer conctac just check in the "updateIA" or "update" functions for events to happen. Then just take the door and say door->doAction("open").
if want it to open on remote sing, then the same.... look for the event, if event happen then
door->doAction("open") nothing rewriten (only the new event OF COURSE).
is is what I doing a "message system" disign?
I realy ask, maybe it is ,but I did not realized it.
take a look at IGUIElement.h found in the include directory.I can see some odd updating conflicts like when one entity sends an already updated entity a message. Messaging seems odd this way too, as I don't know where to process it.
IGUIElement.h is a good example of event handling for gui elements such as text boxes, pulldowns, etc.
with that code, you can get an idea how your game elements handle events from any source supporting the definitions found in IGUIElement.h
for example, you can set up a button to send an event to one of your game element for example a car. also, you can do it vice-versa.
In your case, you will set up a header file IMyGameElement.h and set up all the required code in there.
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
While I agree with keless' analysis (as usual), I will expound a bit further on why I respectfully disagree with the conclusion.
If your goal is to complete a game, then IMO you should:
1) Design it to a fine level of granularity.
2) Implement all of what you designed, and only what you designed.
So keless is completely right, but my counter would be that when your designer changes his mind after you've coded the "naive" implementation of what he originally asked for, your response should be to tell him to
A) Pay the full salary and overheads for all the staff time that he just wasted, just as you'd ask an external paying customer to do if they tried to change their requirements half way through the project.
B) Insert a porcupine backwards where the sun doesn't shine, then squat-jump his way out the door. You've already got a complete design from him; he can push off now and screw up some other project.
That applies especially if you are the designer, and it applies double to a hobbyist project with no external customer or deadlines. Under those dream circumstances, there is absolutely nothing stopping you from doing a Big Design Up Front for the game that you actually want to complete, and then when the temptation to go beyond the minimum requirements of that design becomes strong, remind yourself that You Aren't Gonna Need It in order to finish your game as you designed it.
If you're writing an engine, or an extensible game, or are prepared to working to someone else's changing requirements, then sure, go hog wild on supporting speculative and undefined requirements. But that doesn't put a man on the moon and bring him safely back home, and nor does it get you any closer to finishing your game.
</respectful rant>
If your goal is to complete a game, then IMO you should:
1) Design it to a fine level of granularity.
2) Implement all of what you designed, and only what you designed.
So keless is completely right, but my counter would be that when your designer changes his mind after you've coded the "naive" implementation of what he originally asked for, your response should be to tell him to
A) Pay the full salary and overheads for all the staff time that he just wasted, just as you'd ask an external paying customer to do if they tried to change their requirements half way through the project.
B) Insert a porcupine backwards where the sun doesn't shine, then squat-jump his way out the door. You've already got a complete design from him; he can push off now and screw up some other project.
That applies especially if you are the designer, and it applies double to a hobbyist project with no external customer or deadlines. Under those dream circumstances, there is absolutely nothing stopping you from doing a Big Design Up Front for the game that you actually want to complete, and then when the temptation to go beyond the minimum requirements of that design becomes strong, remind yourself that You Aren't Gonna Need It in order to finish your game as you designed it.
If you're writing an engine, or an extensible game, or are prepared to working to someone else's changing requirements, then sure, go hog wild on supporting speculative and undefined requirements. But that doesn't put a man on the moon and bring him safely back home, and nor does it get you any closer to finishing your game.
</respectful rant>
Last edited by rogerborg on Tue Jan 15, 2008 10:31 pm, edited 2 times in total.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way