我正在写一个自上而下的赛车游戏。这就像“开放世界”游戏,没有圈数,但自由漫游。由于很多原因,我没有使用平铺地图,所以我有一个2048x2048的大背景图像。移动此图像不是导致性能下降的原因。在这张图片上,我插入了一些物理对象来创建墙壁。现在我已经插入了其他汽车来模拟交通,每辆汽车都在一条cgpath上移动,这是一个永远重复的车道。每辆车都响应红绿灯,并通过隐形活动区域和循环cgrectIntersect检查系统停止。这辆车没有物理机身,因为每辆车增加了物理机身,只有3或4辆车后游戏性能不佳......所以我写了一种方法来处理接触,交通信号灯,停车等等......它工作正常但在iphone 4上我只能管理15辆汽车才能获得不良性能。这个性能问题的第一个原因是我写的方法。我正在尝试优化,在我的方法中,我有一些递归循环(例如:对于每次更新,我检查每辆车的内部有另一个循环来检查其他汽车之间的联系人......)
for (int i=0; i<[ArrayCars count]; i++) {
CGRect Frame=[[ArrayCars objectAtIndex:i] frame];
for (int z=0; z<[ArrayCars count]; z++) {
CGRect Frame1=[[ArrayCars objectAtIndex:z] frame];
SKSpriteNode *Car=[ArrayCars objectAtIndex:z];
if (CGRectEqualToRect(Frame,Frame1)==NO && [Car speed]==0) {
if ([self CheckIntersection:Car.frame :Frame]) {
//set some flags that identifies the contact
}
}
}
}
我如何对这样的递归进行优化?我的方法是通过update方法启动的,但是我已经尝试在didEvaluateActions中移动它而没有明显的收益。
答案 0 :(得分:1)
有许多&#34;优化&#34;你可以使用快速枚举开始:
for (SKSpriteNode* car1 in ArrayCars)
{
CGRect Frame1 = car1.frame;
for (SKSpriteNode* car2 in ArrayCars)
{
CGRect Frame2 = car2.frame;
if (CGRectEqualToRect(Frame1, Frame2) == NO && [car2 speed] == 0)
{
if ([self CheckIntersection:Frame2 :Frame1])
{
//set some flags that identifies the contact
}
}
}
}
我打赌这会给你一些改进。
接下来的优化步骤是考虑到每个car2都不需要检查car1。基本上,如果你检查car1和car2是否相撞,car2与car1的反向检查是多余的。
此变体检查每辆车1对所有car2。它会自动跳过支票,而不是以前的车,因为它们已经过检查。因此,每次外循环完成迭代时,内循环的迭代次数越来越少。数学不太好,但我相信这会减少总迭代次数。遗憾的是,您无法对内循环使用快速枚举。
NSUInteger numCars = ArrayCars.count;
int otherCarsStartIndex = 0;
for (SKSpriteNode* car1 in ArrayCars)
{
CGRect Frame1 = car1.frame;
otherCarsStartIndex++;
for (int i = otherCarsStartIndex; i < numCars; i++)
{
SKSpriteNode* car2 = [ArrayCars objectAtIndex:i];
// previous code omitted...
}
}
另一个优化是内联CheckIntersection代码或将其重写为C函数以避免ObjC消息传递开销。
此外,如果您的大多数汽车碰巧有速度== 0,如果您首先枚举ArrayCars以构建仅包含速度非零的汽车的新阵列,那么它可能会提高性能。新阵列可能需要大约原始车辆数量的一半或更少,否则填充新阵列的开销可能太高而无法获得好处。
最后,您可以使用C样式数组来存储您的汽车,从而挤出更多性能,但这需要手动内存管理,并且没有像NSArray那样的缓冲区溢出/下溢保护。
PS:请记住,与其继承者iPhone 4S相比,iPhone 4非常慢。 iPhone 4基本上是一款iPhone 3GS,其33%的速度提升,因其必须为其Retina显示屏绘制四倍的像素而过度征税。