Issues with SKPhysicsBody from Texture

你。 提交于 2021-02-11 13:46:32

问题


I have searched around the internet / StackOverflow for the past few days without much success in finding an answer to a few questions that I believe are intertwined in some way.

  1. How do I prevent my game from freezing when it is rendering an SKPhysicsBody from a texture?
  2. Why are my physics bodies sometimes not created at all, and why are they sometimes the wrong shapes?

Below is the code I am using to try and generate these pillars (image attached at the bottom of the post. There are roughly 6-8 at any point in time before they are removed. When I change the shape to just a rectangle, I get no lag / freezing at all and the physics object is created properly every time.

Is this SKPhysicsBody rendering too complex, or is there a way that I can have my game run smoothly while still generating a correctly shaped physics object? Below is the function I use to set up the walls as they are created in my game.

func createWalls() {

    let scoreNode = SKSpriteNode()

    wallPair = SKNode()
    wallPair.name = "wallPair"

    //MARK: - Top Wall Setup
    let topWall = SKSpriteNode(imageNamed: "Pillar")
    topWall.size = CGSize(width: 100, height: 700)
    topWall.physicsBody = SKPhysicsBody(texture: topWall.texture!, size: topWall.size)
    topWall.position = CGPoint(x: self.frame.maxX+50, y: 0 + 400)
    topWall.physicsBody?.categoryBitMask = PhysicsCategory.Wall
    topWall.physicsBody?.collisionBitMask = PhysicsCategory.Character
    topWall.physicsBody?.contactTestBitMask = PhysicsCategory.Character
    topWall.physicsBody?.isDynamic = false
    topWall.physicsBody?.affectedByGravity = false
    topWall.zRotation = .pi



    //MARK: - Bot Wall Setup
    let botWall = SKSpriteNode(imageNamed: "Pillar")
    botWall.size = CGSize(width: 100, height: 700)
    botWall.physicsBody = SKPhysicsBody(texture: botWall.texture!, size: botWall.size)
    botWall.position = CGPoint(x: self.frame.maxX+50, y: 0 - 400)
    botWall.physicsBody?.categoryBitMask = PhysicsCategory.Wall
    botWall.physicsBody?.collisionBitMask = PhysicsCategory.Character
    botWall.physicsBody?.contactTestBitMask = PhysicsCategory.Character
    botWall.physicsBody?.isDynamic = false
    botWall.physicsBody?.affectedByGravity = false


    scoreNode.size = CGSize(width: 1, height: 600)
    scoreNode.position = CGPoint(x: topWall.position.x+15, y: 0)
    scoreNode.physicsBody = SKPhysicsBody(rectangleOf: scoreNode.size)
    scoreNode.physicsBody?.affectedByGravity = false
    scoreNode.physicsBody?.isDynamic = false
    scoreNode.physicsBody?.categoryBitMask = PhysicsCategory.Score
    scoreNode.physicsBody?.collisionBitMask = 0
    scoreNode.physicsBody?.contactTestBitMask = PhysicsCategory.Character
    scoreNode.color = SKColor.blue

    wallPair.addChild(topWall)
    wallPair.addChild(botWall)
    wallPair.zPosition = 1

    let randomPosition = CGFloat.random(min: -200, max: 200)
    wallPair.position.y = wallPair.position.y + randomPosition
    wallPair.addChild(scoreNode)
    wallPair.run(moveAndRemove)
    self.addChild(wallPair)

}


回答1:


you can use this extension:

extension SKTexture{
  func pristineCopy() -> SKTexture{
      return SKTexture(cgImage:self.cgImage)
  }
}

This should temporarily create a new texture for your physics body to use without getting bogged down by the atlas.

Once the SKPhysicsBody creates the CGPath out of this texture, the memory should get released, so try not to retain it with a variable.

example:

func createWalls()
    let scoreNode = SKSpriteNode()

    wallPair = SKNode()
    wallPair.name = "wallPair"

    //MARK: - Top Wall Setup
    let topWall = SKSpriteNode(imageNamed: "Pillar")
    topWall.size = CGSize(width: 100, height: 700)
    topWall.physicsBody = SKPhysicsBody(texture: topWall.texture!.pristineCopy(), size: topWall.size)
    topWall.position = CGPoint(x: self.frame.maxX+50, y: 0 + 400)
    topWall.physicsBody?.categoryBitMask = PhysicsCategory.Wall
    topWall.physicsBody?.collisionBitMask = PhysicsCategory.Character
    topWall.physicsBody?.contactTestBitMask = PhysicsCategory.Character
    topWall.physicsBody?.isDynamic = false
    topWall.physicsBody?.affectedByGravity = false
    topWall.zRotation = .pi



    //MARK: - Bot Wall Setup
    let botWall = SKSpriteNode(imageNamed: "Pillar")
    botWall.size = CGSize(width: 100, height: 700)
    botWall.physicsBody = SKPhysicsBody(texture: botWall.texture!.pristineCopy(), size: botWall.size)
    botWall.position = CGPoint(x: self.frame.maxX+50, y: 0 - 400)
    botWall.physicsBody?.categoryBitMask = PhysicsCategory.Wall
    botWall.physicsBody?.collisionBitMask = PhysicsCategory.Character
    botWall.physicsBody?.contactTestBitMask = PhysicsCategory.Character
    botWall.physicsBody?.isDynamic = false
    botWall.physicsBody?.affectedByGravity = false


    scoreNode.size = CGSize(width: 1, height: 600)
    scoreNode.position = CGPoint(x: topWall.position.x+15, y: 0)
    scoreNode.physicsBody = SKPhysicsBody(rectangleOf: scoreNode.size)
    scoreNode.physicsBody?.affectedByGravity = false
    scoreNode.physicsBody?.isDynamic = false
    scoreNode.physicsBody?.categoryBitMask = PhysicsCategory.Score
    scoreNode.physicsBody?.collisionBitMask = 0
    scoreNode.physicsBody?.contactTestBitMask = PhysicsCategory.Character
    scoreNode.color = SKColor.blue

    wallPair.addChild(topWall)
    wallPair.addChild(botWall)
    wallPair.zPosition = 1

    let randomPosition = CGFloat.random(min: -200, max: 200)
    wallPair.position.y = wallPair.position.y + randomPosition
    wallPair.addChild(scoreNode)
    wallPair.run(moveAndRemove)
    self.addChild(wallPair)
}


来源:https://stackoverflow.com/questions/59637314/issues-with-skphysicsbody-from-texture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!