在iOS 9上SpriteKit物理大量FPS下降

时间:2016-10-24 22:14:03

标签: ios sprite-kit game-physics skphysicsbody

我在场景中遇到巨大的FPS下降,其中有一些静态SKSpriteNode节点,这些节点的主体定义为SKPhysicsBody init(polygonFrom: CGPath)以及一些简单的动态SKSpriteNode节点使用init(rectangleOf: CGSize)定义的实体。

动态节点在场景中触发并最终休息,具体取决于物理特性。每个动态节点都与其他动态节点冲突,也与之前提到的静态节点冲突。

游戏以60fps平稳运行,直到屏幕上的动态节点数量约为30或更多。之后,FPS开始大幅下降到10fps左右。

注1 :iOS 10上没有问题,仅限iOS 9 (我没有测试iOS 8,因为我不支持它)。< / p>

注意2 :由于动态节点数量增加,绘制调用不会增加,因此OpenGL方面似乎没有问题。

注意3 :我已禁用contactTestBitMask以确保这不是问题的原因。

我使用 Time Profiler 运行了Instruments,专注于FPS下降的段,发现了以下奇怪的事情:

Time Profiler details

奇怪的是,在有问题的细分中超过50%的时间用于PhysicsKit 。请注意,此时是否发生碰撞或者动态节点是否只是放置在原位并不重要。结果总是一样的。

这必须是它的原因,但由于所有这些都发生在系统库(PhysicsKit)中,我真的不知道在我的代码库中查找问题的位置。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

没有办法解决你的问题,因为nateslager已经提到了明显的问题,我只是告诉你一个解决方案。

你所做的是你将场景分成象限或更多,并且有某种重叠,你为这些象限保留categoryBitMask,因为物理对象可以有多个categoryBitMask。现在你需要每帧更新这些类别,所以我想覆盖position属性并添加didSet来告诉节点他们所在的象限。

现在这可能变得非常复杂,具体取决于你如何使用这些标志,因为你不能做像quadrant4&amp;不好,因为那时它仍会记录好坏。相反,您需要quadrant4bad作为1类。我们的想法是减少所有机构之间的检查次数。

E.G。 我们有一个场景是(-5,-5)到(5,5),大小为(11,11)

quadrant1是(-5,0),(0,0),( - 5,-5),(0,-5)
象限2是(0,0),(5,0),(0,-5),(5,-5)
象限3是(-5,5),(0,5),( - 5,0),(0,0)
象限4是(5,0),(5,5),(0,0),(5,0)
quadrantC为(-2.5,2.5),(2.5,2.5),( - 2.5, - 2.5),(2.5,2.5)

enum PhysicsCategory : UInt
{
   case good = 0b1
   case quadrant1Bad = 0b10
   case quadrant2Bad = 0b100
   case quadrant3Bad = 0b1000
   case quadrant4Bad = 0b10000
   case quadrantCBad = 0b100000
}

//we set up a good player at position 0,0 so he is in the center quadrant
good.contactBitMask = quadrantC


//we set up a enemy  at position -5, -5 so he is in the first quadrant
bad1.contactBitMask = quadrant1

//we set up a enemy  at position 5, -5 so he is in the second quadrant
bad2.contactBitMask = quadrant2

//we set up a enemy  at position -5, 5 so he is in the third quadrant
bad3.contactBitMask = quadrant3

//we set up a enemy  at position 5, 5 so he is in the fourth quadrant
bad4.contactBitMask = quadrant4

//we set up a enemy  at position -2.5, 2.5 so he is in the third quadrant and center quadrant (remember, they have a width and height to them, so they will be in more than 1 quadrant
badC.contactBitMask = quadrant3 | quadrantC

现在我们的游戏正在运行时,只会检查其象限中的敌人,所以只能在quadrantC上进行检查

如果good进入quadrant3,那么只会进行2次检查,bad3和badC

这将有助于减少物理学后端的调用,这样可以减少滞后。

如果您碰巧使用了很多不同的类别,那么我建议您不要使用多个位掩码,当敌人不在某个象限时关闭敌人的categoryBitMasks。这也将减少物理引擎完成的检查次数。

答案 1 :(得分:0)

即使你只有“几个”多边形物理体,每个额外的矩形物理体,无论它是否在移动,都需要与每个帧中计算的每个多边形物理体的距离(因此b2Distance()func) 。尝试降低多边形物理实体的复杂性/数量,以提高帧速率。

我怀疑性能突然下降与缓存(b2SimplexCache)有关,缓存(b2SimplexCache)存储这些距离达到其最大容量(可能约为30个值),此时缓存未命中率正在降低帧速率。 iOS 10必须增加此缓存。另一个解决方案是在iOS 9中以某种方式增加此功能的缓存,尽管我不确定如何。