English 中文(简体)
Game loop performance and component approach
原标题:

I have an idea of organising a game loop. I have some doubts about performance. May be there are better ways of doing things.

Consider you have an array of game components. They all are called to do some stuff at every game loop iteration. For example:

GameData data; // shared
app.registerComponent("AI", ComponentAI(data) );
app.registerComponent("Logic", ComponentGameLogic(data) );
app.registerComponent("2d", Component2d(data) );
app.registerComponent("Menu", ComponentMenu(data) )->setActive(false);
//...
while (ok)
{
//...
app.runAllComponents();
//...
}

Benefits:

  1. good component-based application, no dependencies, good modularity
  2. we can activate/deactivate, register/unregister components dynamically
  3. some components can be transparently removed or replaced and the system still will be working as nothing have happened (change 2d to 3d)(team-work: every programmer creates his/her own components and does not require other components to compile the code)

Doubts:

  1. inner loop in the game loop with virtual calls to Component::run()
  2. I would like Component::run() to return bool value and check this value. If returned false, component must be deactivated. So inner loop becomes more expensive.

Well, how good is this solution? Have you used it in real projects?

最佳回答

Some C++ programmers have way too many fears about the overhead of virtual functions. The overhead of the virtual call is usually negligible compared to whatever the function does. A boolean check is not very expensive either.

Do whatever results in the easiest-to-maintain code. Optimize later only if you need to do so. If you do find you need to optimize, eliminating virtual calls will probably not be the optimization you need.

问题回答

In most "real" games, there are pretty strict requirements for interdependencies between components, and ordering does matter.

This may or may not effect you, but it s often important to have physics take effect before (or after) user interaction proecssing, depending on your scenario, etc. In this situation, you may need some extra processing involved for ordering correctly.

Also, since you re most likely going to have some form of scene graph or spatial partitioning, you ll want to make sure your "components" can take advantage of that, as well. This probably means that, given your current description, you d be walking your tree too many times. Again, though, this could be worked around via design decisions. That being said, some components may only be interested in certain portions of the spatial partition, and again, you d want to design appropriately.

I used a similar approach in a modular synthesized audio file generator.

I seem to recall noticing that after programming 100 different modules, there was an impact upon performance when coding new modules in.

On the whole though,I felt it was a good approach.

Maybe I m oldschool, but I really don t see the value in generic components because I don t see them being swapped out at runtime.

struct GameObject
{
   Ai* ai;
   Transform* transform;
   Renderable* renderable;
   Collision* collision;
   Health* health;
};

This works for everything from the player to enemies to skyboxes and triggers; just leave the "components" that you don t need in your given object NULL. You want to put all of the AIs into a list? Then just do that at construction time. With polymorphism you can bolt all sorts of different behaviors in there (e.g. the player s "AI" is translating the controller input), and beyond this there s no need for a generic base class for everything. What would it do, anyway?

Your "update everything" would have to explicitly call out each of the lists, but that doesn t change the amount of typing you have to do, it just moves it. Instead of obfuscatorily setting up the set of sets that need global operations, you re explicitly enumerating the sets that need the operations at the time the operations are done.

IMHO, it s not that virtual calls are slow. It s that a game entity s "components" are not homogenous. They all do vastly different things, so it makes sense to treat them differently. Indeed, there is no overlap between them, so again I ask, what s the point of a base class if you can t use a pointer to that base class in any meaningful way without casting it to something else?





相关问题
What to look for in performance analyzer in VS 2008

What to look for in performance analyzer in VS 2008 I am using VS Team system and got the performance wizard and reports going. What benchmarks/process do I use? There is a lot of stuff in the ...

SQL Table Size And Query Performance

We have a number of items coming in from a web service; each item containing an unknown number of properties. We are storing them in a database with the following Schema. Items - ItemID - ...

How to speed up Visual Studio 2008? Add more resources?

I m using Visual Studio 2008 (with the latest service pack) I also have ReSharper 4.5 installed. ReSharper Code analysis/ scan is turned off. OS: Windows 7 Enterprise Edition It takes me a long time ...

Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

热门标签