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

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

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

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

注1:iOS 10上没有问题,只有iOS 9(我没有测试iOS 8,因为我不支持它).

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

注3:我禁用了contactTestBitMask以确保这不是问题的原因.

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

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

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

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

谢谢你的帮助!

最佳答案 没有办法解决你的问题,因为nateslager已经提到了明显的问题,我将告诉你一个解决方案.

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

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

例如.
我们有一个场景是(-5,-5)到(5,5),大小为(11,11)

quadrant1是(-5,0),(0,0),( – 5,-5),(0,-5)
quadrant2是(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上进行检查

如果好进入象限3,那么只会进行2次检查,bad3和badC

这将有助于减少物理学后端的调用,这样可以减少延迟.

如果你碰巧有很多不同的类别,那么我会建议你不要使用多个bitmaskes,当你的敌人不在某个象限时关掉敌人的categoryBitMasks.这也将减少物理引擎完成的检查次数.

点赞