带有内部 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 不起作用
HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js