I am writing my own game which handles large amount of game entities (count is ≈1000). Every entity must be drawn on screen. At开发者_如何学JAVA the beginning i wasn't sure that C# will give me a good framerate. But then, when i applied some basic culling i was shocked by the even more higher framerate.
So now, when i am adding AI logic to entities, the update time for every object takes a some amount of time. I have lists with objects and i looping trough them and calling obj.Update(dt). Looks like this way isn't best. Update of "huge" entities can take a lot of ms's, so others will need to wait when that guy will finish its own update.
So my question is: which way is the better when managing huge amount of dynamic objects?
The problem you have is that you're looping through the objects calling your Update
method. What if something isn't updating? What if something doesn't need to be updated every frame?
Better to add an event to your main loop and have your objects subscribe to it:
public void FrameListener(float _ticks);
public class Game
{
public Event FrameListener OnFrame;
}
Now, whenever anything needs to update, it just subscribes to this event (getting the delta-tick count passed to it). When an object becomes idle, it can unsubscribe itself. Using this method, only objects that need updating are getting updated.
Also, you could add a counter to the subscription process (meaning you might ditch the event object in favor of a AddListener()
type methods), telling the system only to invoke the delegate every 'n' frames. In a game where you might have building production for example (Settlers, Civilization, etc), it makes no sense for these things to update their production every frame. Even every 5 seconds is enough. This cuts a lot of overhead out, when you can define exactly how often an objects needs to be updating.
Static objects just never instill a delegate, so never cause any overhead.
Firstly, 1000 objects isn't really huge. At 60 fps, that's 60 kHz, which is 16 µs — at least 32,000 clock cycles on most hardware — per object. Some objects must be incurring a high cost.
Assuming you can't bring the per-object cost down, you could allocate a total time budget for updating objects, and stop the loop when that time elapses, but keep looping from the same spot on the next frame, wrapping around to the start if you still have more time left when you reach the end. In short, run around a ring buffer, stopping to render a frame whenever your time runs out.
I think your problems is not related to game development but to general performances principles.
You probably have to explore multiples ways of optimizing performance. Here is list but non exhaustive :
- multi threading/parallelism : can achieve very good ameliorations but can add a lot of complexity in your application. If you use c# 4, you may take a look at the new Parallel library
- depending of the version and edition of your VS, you can activate the code analysis (or use FXcop if not available in VS). The tool can provide good advices
- use profiling tools to discover the bottleneck of you code
- use tools to analyze the complexity of your code, especially the cyclomatic complexity
- google a bit for general performance tips (string builder VS string concatenation, etc.)
- google a bit more for hardcode performance tip (change the order of the parameters in the methods, reduce the use of value variable, reduce the call graph, etc.)
A tip for more specific game dev (from a newbie in game dev I admit): * try to partition your objects in subsets instead of a single set... it's sometimes more efficient to have a graph of objects, instead a list of objects. You can update a single node of the graph instead of the whole objects * exclude if possible updates of non displayed objects
精彩评论