PhysicsBody: Could not create physics body

混江龙づ霸主 提交于 2020-05-24 05:31:28

问题


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?


回答1:


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.




回答2:


The Problem

SKTextureAtlas doesn't immediately load textures into memory. Oh no!

An inelegant solution

Calling a texture's size method before creating the physicsbody will force load it into memory.

let atlasName = "player"
let textureName = "bird0001"

let atlas = SKTextureAtlas(named: atlasName)
let texture = atlas.textureNamed(textureName)

texture.size() //Force load into memory

let node = SKSpriteNode(texture: texture)
node.physicsBody = SKPhysicsBody(texture: texture, size: node.size)

Some other notes

A few years ago, I used to immediately load my entire atlas into memory using the atlas.preload { } method, but this method had a memory leak bug. I found an alternative way to force load a sktexture atlas using texture.size()



来源:https://stackoverflow.com/questions/59961842/physicsbody-could-not-create-physics-body

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