【问题标题】:PhysicsBody: Could not create physics bodyPhysicsBody:无法创建物理体
【发布时间】:2020-01-29 06:54:09
【问题描述】:

我在 App Store 上有一个完整的可运行游戏,但从 iOS 13 开始,它根本无法运行。我已经通过 Xcode 将游戏安装到我的设备上,但出现了很多错误:

PhysicsBody:无法创建物理体。

我一直在像这样创建我的 SKSpriteNode:

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

根据一些研究,这可能是 iOS 和 Xcode 的一个持续存在的错误。有人可以确认是否是这种情况,因为对于使用纹理创建 SKSpriteNodes 的应用商店上的游戏来说,这似乎是一个主要问题?

在需要纹理的地方有解决办法吗?

【问题讨论】:

  • 是的,这是一个错误。至少对我们来说,来自地图集之外的纹理的物理实体是有效的。我们通过复制资产的非纹理版本并从中构建物理体来避免这个问题。如果你不能这样做并且不能使用圆形或矩形体之类的替代方案,也许制作一个精灵,然后使用 SKView 的texture(from:)texture(from:crop:) 会给出一个可以工作的纹理。不过我没试过。
  • 我在这里的某处提供了临时修复此错误的代码
  • 嘿 Knight0fDragon,这很好。你能不能链接到那个?
  • 不知道我在哪里发的,如果你搜索这个错误,你应该可以找到它。
  • texture(from:) 确实会生成可用于成功创建物理体的纹理。请参阅下面的答案,了解哪些有效,哪些无效。

标签: swift sprite-kit


【解决方案1】:

好的,从 iOS 13.3(编辑现在也在 13.3.1 上尝试)和 Xcode 版本 11.3 开始,这是对避免此错误的不同方法的测试。此链接的完整测试源代码:

https://github.com/bg2b/bugtest

相关代码:

  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")
  }

总结:

  1. 简单地从图集中引用纹理并制作物理体可能会失败
  2. 在制作主体失败之前通过调用size() 强制加载纹理
  3. 尝试通过cgImage() 制作新纹理失败(图像本身已损坏,可能与相同的错误有关)
  4. 使用视图渲染到纹理,然后使用该新纹理制作物理主体
  5. 从纹理作品的非图集副本制作物理主体

测试程序的控制台输出显示哪些有效,哪些无效:

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

这是一个屏幕截图,显示了不同方法的效果。您必须仔细观察,但只有最后两个具有有效的物理实体。

【讨论】:

  • 是的!似乎最简单的解决方案是停止使用纹理图集。这是我工作量最少的游戏中最简单的过渡。
  • 我回到 iOS 开发,仍然使用 Obj-C。我有这个确切的问题,但需要从 swift 中“翻译”。您出色的摘要中的解决方案4正是我所追求的。你有机会为我提供翻译吗?我错过了 view.texture 调用,不确定如何实现...感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多