简体   繁体   English

FPS下降和游戏速度减慢 - Sprite-Kit和Swift

[英]FPS drops and game slows down - Sprite-Kit and Swift

I have a game using Sprite-Kit and Swift where I generate random circles falling from the top of the screen to the bottom of the screen. 我有一个使用Sprite-Kit和Swift的游戏,我生成从屏幕顶部落到屏幕底部的随机圆圈。

When launching the game, it runs perfectly fine at the beginning (at around 60 FPS or less) but then the FPS drops gradually and the game becomes extremely slow... I don't understand why the FPS drops with time (the number of nodes stays good at around 8-10, so they get removed when they go off the screen) - I tested it on both the iOS Simulator and an actual device, any ideas? 当启动游戏时,它在开始时运行完全正常(大约60 FPS或更低)然后FPS逐渐下降并且游戏变得非常慢......我不明白为什么FPS会随着时间的推移而下降(数量)节点在8-10左右保持良好状态,因此当它们离开屏幕时它们会被移除) - 我在iOS模拟器和实际设备上测试了它,任何想法?

I have checked, the problem isn't coming from a memory leak. 我已经检查过,问题不是来自内存泄漏。 Also, I am using only one view controller. 另外,我只使用一个视图控制器。

The only function that I think could cause this issue is this one, but I don't know why: 我认为唯一能引起这个问题的功能就是这个,但我不知道为什么:

/* Function to generate single random circle */
func generateCircle() -> Void {
    let circleSize:CGFloat = CGFloat(arc4random_uniform(40) + 3)
    let xPosition:CGFloat = CGFloat(arc4random_uniform(UInt32(size.width)))

    var randomCircle = SKShapeNode(circleOfRadius: circleSize)
    randomCircle.strokeColor = SKColor.redColor()
    randomCircle.fillColor = SKColor.redColor()
    randomCircle.physicsBody = SKPhysicsBody(circleOfRadius: circleSize)
    randomCircle.physicsBody?.dynamic = false
    randomCircle.position = CGPoint(x: xPosition, y: size.height + circleSize*2)
    randomCircle.physicsBody?.dynamic = true
    randomCircle.physicsBody?.categoryBitMask = randomCirclesGroup
    addChild(randomCircle)
}

Maybe there is a memory leak. 也许有内存泄漏。

  1. Launch your game with Xcode. 使用Xcode启动游戏。
  2. Open the Xcode Debug Navigator panel with CMD + 6 . 使用CMD + 6打开Xcode Debug Navigator面板。
  3. Select Memory and wait to see if the allocated memory grows up. 选择内存并等待分配的内存是否增长。

If this happen, I mean if the allocated memory continue to grow even when you know it should not, then you are leaking memory. 如果发生这种情况,我的意思是如果分配的内存继续增长,即使你知道它不应该,那么你正在泄漏内存。

And the best tool to find where exactly is the problem in your code is Instruments . 找到代码中问题的最佳工具是Instruments

I've had this before, the node count makes it look they are gone, but they really aren't. 我之前已经有了这个,节点数使它看起来已经消失了,但实际上并非如此。

You need to remove the circles from the view to really get rid of them. 您需要从视图中删除圆圈才能真正摆脱它们。

First you would define a set (inside your class, but not inside any function) 首先你要定义一个集合(在你的类中,但不在任何函数内)

 let circles = Set<SKShapeNode>()

then in the generateCircle() function you would say: 然后在generateCircle()函数中你会说:

 circles.insert(randomCircle)

Then in the update() function: 然后在update()函数中:

 override func update(currentTime: CFTimeInterval){
      for index in circles {
           if index.position.y <= 0 {
                index.removeFromParent()
                circles.remove(index)
           }
      }
 }

Basically what this does is, at every frame, check if any of the circles are lower than the bottom of the screen, and deletes them if they are. 基本上它的作用是,在每一帧,检查是否有任何圆圈低于屏幕底部,如果是,则删除它们。

SKShapeNode has worse performance compared to SKSpriteNode and one should try to avoid using SKShapeNode if at all possible. SKShapeNode相比具有更糟糕的表现SKSpriteNode并应尽量避免使用SKShapeNode如果在所有可能的。

From Apple's documentation : 来自Apple的文档

Shape nodes are useful for content that cannot be easily decomposed into simple textured sprites. 形状节点对于无法轻易分解为简单纹理精灵的内容非常有用。 Shape nodes are also very useful for building and displaying debugging information on top of your game content. 形状节点对于在游戏内容之上构建和显示调试信息也非常有用。 However, the SKSpriteNode class offers higher performance than this class, so use shape nodes sparingly. 但是,SKSpriteNode类提供比此类更高的性能,因此请谨慎使用形状节点。

If you really want to use SKShapeNode s (perhaps because it's easy for prototyping) I would advise you to do the following: 如果你真的想使用SKShapeNode (也许是因为它很容易进行原型设计),我建议你做以下事情:

  • Create textures for your shapes a single time, perhaps when the scene gets loaded. 一次为曲线创建纹理,可能是在场景加载时。
  • Cache the rendered textures. 缓存渲染的纹理。 In your situation a dictionary with size and texture seems appropriate, eg [CGSize: SKTexture] . 在您的情况下,具有大小和纹理的字典似乎是合适的,例如[CGSize: SKTexture]
  • From then on, whenever you need a shape, retrieve the texture from the cache and display them using an SKSpriteNode . 从那时起,无论何时需要形状,都要从缓存中检索纹理并使用SKSpriteNode显示它们。

To render an SKShapeNode into a texture you can use SKView's textureFromNode function : 要将SKShapeNode渲染为纹理, 您可以使用SKView的textureFromNode函数

Renders the contents of a node tree and returns the rendered image as a SpriteKit texture. 呈现节点树的内容并将呈现的图像作为SpriteKit纹理返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM