带有内部 box2d 物理崩溃的 SpriteKit 游戏

Posted

技术标签:

【中文标题】带有内部 box2d 物理崩溃的 SpriteKit 游戏【英文标题】:SpriteKit game with internal box2d physics crash 【发布时间】:2021-08-31 18:42:44 【问题描述】:

我正在尝试调试 SpriteKit 的物理引擎(可能是 box2d 顶部的包装器)中的崩溃。我的应用启用了位码,所以我必须在上传到 AppStoreConnect 后下载 DSYM,我最终得到了这个:

1CrashDoctor Diagnosis: Attempted to dereference null pointer.
2Thread 0 Crashed:
0   PhysicsKit                          0x00000001c1d77e58 b2Fixture::Create(b2Body*, b2FixtureDef const*)
1   PhysicsKit                          0x00000001c1d7556c b2Body::CreateFixture(b2FixtureDef const*)
2   PhysicsKit                          0x00000001c1d7556c b2Body::CreateFixture(b2FixtureDef const*)
3   PhysicsKit                          0x00000001c1d61ef8 __26-[PKPhysicsWorld addBody:]_block_invoke
4   PhysicsKit                          0x00000001c1d64aa0 -[PKPhysicsWorld(Private) _runBlockOutsideOfTimeStep:]
5   PhysicsKit                          0x00000001c1d61da4 -[PKPhysicsWorld addBody:]
6   SpriteKit                           0x00000001b7b98940 -[SKNode setPhysicsBody:]
107   PlugBW                              0x0000000100ebf870 addPhysicsBody + [PhysicsHelper.swift : 28] 
118   PlugBW                              0x0000000100ec04d4 helper_dropFruitAndRefreshCurrentFruit + [Playground.swift : 158] 
129   PlugBW                              0x0000000100ebc9d4 touchesEnded + [AnalyticsHelper.swift : 23] 

在某些情况下,两个相关的功能是:

PhysicsHelper.swift:

  static func addPhysicsBody(fruit: FruitUI) 
    let body = SKPhysicsBody(circleOfRadius: fruit.size.height/2)
    body.categoryBitMask = fruit.fruit.bitMask
    body.contactTestBitMask = Fruit.allFruitsBitMask
    
    fruit.physicsBody = body
    fruit.droppedAt = Date()
  

Playground.swift:

  func helper_dropFruitAndRefreshCurrentFruit() 
    let droppedFruit = currentFruitUI
    PhysicsHelper.addPhysicsBody(fruit: droppedFruit)
    droppedFruit.dropPath?.removeFromParent()
    droppedFruitUIs += [droppedFruit]
    
    currentFruitUI = FruitUI(fruit: LevelDesigner.randomFruit(usedFruitCount: &usedFruitCount), isInitial: true, state: store.state)
    helper_addCurrentFruit()
  

由于我使用的是swift,所以出现这个NPE崩溃很奇怪。我怀疑这可能是 SpriteKit 或 box2d 下面的错误?

编辑:

我觉得这个功能有点可疑:_runBlockOutsideOfTimeStep。这表明xxx.physicsBody = xxx 将一个异步块排入队列,稍后在某些东西被释放后执行,因此是 NPE。但是,我不是 box2d 或 SpriteKit 内部的专家。

编辑 2:

google 的结果并不多,但我发现了这个类似的未回答问题:https://developer.apple.com/forums/thread/28357

但是,我的崩溃发生在 ios 14 上。

编辑 3:

以防万一,这个函数被频繁地调用(每次掉一个水果,这是用户在这个游戏中的主要动作),但它只在不到总用户的 1% 的情况下崩溃。

【问题讨论】:

您通常只需要为自己的应用获取 DSYM,而不需要为任何内置框架获取 DSYM 这里有类似的问题。我将开始赏金。 【参考方案1】:

添加一个数组/列表并添加创建的水果。这将保留对水果对象的附加引用并防止取消引用空指针异常。 数组/列表应位于游戏关卡结束前不会超出范围的位置。 例如:

    主屏幕 如果在关卡开始之前创建了 Fruit 对象,请在此处添加到数组/列表中 玩过的游戏 关卡完成后,从数组/列表中移除水果对象。

【讨论】:

水果已保留。否则,由于 swift 的 null 安全性,我们甚至根本无法访问它们。 @约翰。从这个问题中,我了解到您有工作代码,除了对象在被删除后被引用的少数情况。这是空指针异常的原因。答案显示了添加另一个引用以便不删除对象的想法。您还可以尝试确保函数 addPhysicsBody 在调用 dropFruit removeFromParent 之前完成(如果这是删除引用。) 这听起来很 hacky 补丁,并且可能会引入未来的错误。 Swift 语言应该已经涵盖了您描述的情况。

以上是关于带有内部 box2d 物理崩溃的 SpriteKit 游戏的主要内容,如果未能解决你的问题,请参考以下文章

带有 box2d 联系人监听器的 cocos2dx 不起作用

Qt 5.10 集成 Box2D 物理引擎

Box2d刚体轨迹预测

HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js

实例介绍Cocos2d-x中Box2D物理引擎:碰撞检測

Libgdx 游戏在 Android 上崩溃