4

I have an entire working game that has been up on the App Store, but since iOS 13 it simply does not work. I've installed the game onto my device via Xcode and I'm getting a lot of errors coming up saying:

PhysicsBody: Could not create physics body.

I've been creating my SKSpriteNodes like this:

 let bird = SKSpriteNode(texture: SKTextureAtlas(named:"player").textureNamed("bird0001"))
 bird.physicsBody = SKPhysicsBody(texture: bird.texture!,
                                         size: bird.size)

Based on some research, this is possibly an ongoing bug with iOS and Xcode. Could someone please confirm if this is the case, as this seems to be like a major problem for Games on the app store that create their SKSpriteNodes using textures?

Is there a fix to this where textures are needed?

dub
  • 441
  • 1
  • 3
  • 17
  • 1
    Yes, it's a bug. At least for us, physics bodies from textures that are not in an atlas work. We avoided the issue by having duplicate non-texture versions of assets and building the physics bodies from those. If you can't do that and can't use an alternative like a circular or rectangular body, maybe making a sprite and then using SKView's `texture(from:)` or `texture(from:crop:)` would give a texture that would work. I haven't tried that though. – bg2b Jan 29 '20 at 12:39
  • I provided code somewhere on here that temp fixes this bug – Knight0fDragon Jan 29 '20 at 21:50
  • Hey Knight0fDragon, that's good. Would you perhaps be able to link to that? – dub Jan 29 '20 at 23:13
  • No idea where I posted it, if you search for this bug, you should be able to find it. – Knight0fDragon Jan 30 '20 at 14:26
  • `texture(from:)` does produce a texture that can be used for successful creation of a physics body. See answer below for a summary of what works and what does not. – bg2b Feb 01 '20 at 17:22

1 Answers1

4

OK, here's a test of different approaches for avoiding this bug as of iOS 13.3 (edit also now tried on 13.3.1) and Xcode version 11.3. Full source of the test at this link:

https://github.com/bg2b/bugtest

Relevant code:

  func addShip(_ texture: SKTexture, how: String) {
    let sprite = SKSpriteNode(texture: texture)
    sprite.position = CGPoint(x: x, y: 0)
    sprite.zRotation = .pi / 4
    x += 100
    sprite.physicsBody = SKPhysicsBody(texture: texture, size: sprite.size)
    if sprite.physicsBody == nil {
      print("\(how) failed")
    } else {
      print("\(how) worked")
    }
    addChild(sprite)
  }

  override func didMove(to view: SKView) {
    // The atlas version of a texture
    addShip(SKTexture(imageNamed: "ship_blue"), how: "simple atlas reference")
    // From an atlas, but call size() to force loading
    let texture = SKTexture(imageNamed: "ship_blue")
    _ = texture.size()
    addShip(texture, how: "atlas force load")
    // Reconstruct via CGImage (size would be wrong because of 2x)
    let cgTexture = SKTexture(cgImage: texture.cgImage())
    addShip(cgTexture, how: "reconstruct via cgImage")
    // Re-render using view
    let renderedTexture = view.texture(from: SKSpriteNode(texture: texture))!
    addShip(renderedTexture, how: "re-render using view")
    // Non-atlas texture
    addShip(SKTexture(imageNamed: "nonatlas_ship_blue"), how: "not in atlas")
  }

Summary:

  1. Simply referencing the texture from an atlas and making the physics body may fail
  2. Force-loading the texture by calling size() before making the body fails
  3. Trying to make a new texture by going through cgImage() fails (the image itself is broken, probably related to the same bug)
  4. Rendering to a texture using a view and then making the physics body from that new texture works
  5. Making the physics body from a non-atlas copy of the texture works

Console output from the test program showing what works and what does not:

2020-02-01 06:23:51.872975-0500 bugtest[14399:9898087] PhysicsBody: Could not create physics body.
simple atlas reference failed
2020-02-01 06:23:51.886387-0500 bugtest[14399:9898087] PhysicsBody: Could not create physics body.
atlas force load failed
2020-02-01 06:23:51.913927-0500 bugtest[14399:9898087] PhysicsBody: Could not create physics body.
reconstruct via cgImage failed
re-render using view worked
not in atlas worked

Here's a screen shot showing the effect of the different approaches. You have to look a bit closely, but only the last two have valid physics bodies.

Screen shot of different attempts

bg2b
  • 1,939
  • 2
  • 11
  • 18
  • Yup! Seems the most simple solution is to stop using texture atlas. This has been the most simple transition for my games with the least amount of work. – dub Feb 11 '20 at 06:53
  • I'm coming back to iOS dev, and still using Obj-C. I having this exact problem, but need to "translate" from swift. Solution 4 from your excellent summary is just what I'm after. Any chance you provide a translation for me? I'm missing the view.texture call, not certain how to implement... thanks for any help. – VariableSquid Oct 20 '20 at 13:55