问题
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.
- How do I prevent my game from freezing when it is rendering an SKPhysicsBody from a texture?
- 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