我正在使用Objective-C和Cocoa-Touch开发我的第一款iPad游戏,并在游戏循环中遇到一些性能问题。
每个游戏对象都由CALayer
观察,当发生变化时,它会在屏幕上绘制游戏对象。我在tutorial on Cocoa with Love中看到了这个设计并且喜欢这个想法。
在游戏循环中,我使用以下代码更新游戏对象:
NSArray *allKeys = [gameObjects allKeys];
NSLog(@"fps: %.5f; %d game objects", 1.0 / frameDuration, [allKeys count]); // profiling
// update game 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];
}
虽然这对于少于30个游戏对象非常有效,但对于超过30个游戏对象,帧速率从30 fps降至15 fps。
当我省略hasChanges
电话并且每次只调用[gameObjects didChangeValueForKey:gameObjectKey];
时,我可以保持每秒30帧。为什么?要求游戏对象进行更改比告诉游戏对象的字典值更改迫使图层更新自身更昂贵吗?这有意义吗?
我还使用分析来找出导致性能问题的确切原因,但我无法真正处理这些工具。
感谢您的帮助!
答案 0 :(得分:2)
摆脱gameObject
的保留/释放,因为它是多余的。
此外,您正在调用willChangeValueForKey
,但并不总是调用didChangeValueForKey
,而应该是balanaced,这可能会导致性能问题。什么是gameObjects
?你确定它还不符合KVO吗?你确定它需要吗?如果是这样,为什么?如果删除所有KVO内容,代码是否仍然有效?
编辑...新代码:
// 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];
}
}
这有用吗?冗余保留/释放移动和平衡KVO通知。让willChange
和didChange
相邻是技术上不好的,但在这种情况下可能没问题。