Performance issues in game loop
I'm developing my first iPad game in Objective-C and Cocoa-Touch and have some performance issues in the game loop.
Every game object is observed by a CALayer
which draws the game object on the screen when changes occur. I've seen this design in a tutorial on Cocoa with Love and liked the idea.
In the game loop I use the following code to update the game objects:
NSArray *allKeys = [gameObjects allKeys];
NSLog(@"fps: %.5f; %d game objects", 1.0 / frameDuration, [allKeys count]); // profiling
// update ga开发者_运维百科me objects
for (NSString *gameObjectKey in allKeys) {
[gameObjects willChangeValueForKey:gameObjectKey];
GameObject *gameObject = [[self gameObjectForKey:gameObjectKey] retain];
if ([gameObject updateWithTimeInterval:frameDuration]) {
[self removeGameObjectForKey:gameObjectKey];
}
if ([gameObject hasChanges]) {
[gameObjects didChangeValueForKey:gameObjectKey];
gameObject.changes = 0; // reset changes
}
[gameObject release];
}
While this works great for less than 30 game objects, frame rate drops from 30 fps down to 15 for more than 30 game objects.
When I omit the hasChanges
call and just call [gameObjects didChangeValueForKey:gameObjectKey];
every single time, I can maintain the 30 frames per second. Why? Is it more expensive to ask a game object for changes than to tell the game objects' dictionary that a value has changed which forces a layer to update itself? Does that make sense?
I also used profiling to find out what exactly causes the performance issues, but I can't really handle the Instruments tools.
Thanks for your help!
Get rid of the retain/release of gameObject
as it is redundant.
Also, you are calling willChangeValueForKey
, but not always calling didChangeValueForKey
, when they should be balanaced, which might be causing the perfomance issue. What is gameObjects
? Are you sure its not already KVO compliant? Are you sure it needs to be? If so, why? Does the code still work if you remove all the KVO stuff?
Edit...new code:
// update game objects
for (NSString *gameObjectKey in allKeys) {
GameObject *gameObject = [self gameObjectForKey:gameObjectKey];
bool objectDead = [gameObject updateWithTimeInterval:frameDuration];
if ([gameObject hasChanges]) {
[gameObjects willChangeValueForKey:gameObjectKey];
[gameObjects didChangeValueForKey:gameObjectKey];
gameObject.changes = 0; // reset changes
}
if (objectDead) {
[self removeGameObjectForKey:gameObjectKey];
}
}
Does this work? Redundant retain/release moved and balanced KVO notifications. Its techically bad to have the willChange
and didChange
adjacent, but in this case is probably ok.
精彩评论