Running a SpriteKit
particle system in the overlaySKScene
property of a SCNView
causes the app to crash with the stack trace below.
Based on the stack trace, it seems like it's all system code running so how are you supposed to debug the crash, and more importantly, identify if it's a bug with SceneKit/SpriteKit or a bug in the app?
For what it's worth, below is the function that adds the particle system, but it's not referenced in the stack trace.
fileprivate func animateFireworks(scnPoint: CGPoint, color: UIColor) {
// Set emitter properties
let particleBirthRate = CGFloat(150)
let maxParticles = 50
let numEmitters = 5
// SceneView point -> SpriteKit point
let skOverlayPoint = skOverlay.convertPoint(fromView: scnPoint)
// Create emitters
for _ in 0..<numEmitters {
let fireworksEmitter = SKEmitterNode(fileNamed: ExplosionEmitterFilename)!
// Set particle size
let particleSize = CGSize(width: 20, height: 20)
fireworksEmitter.particleSize = particleSize
// Set color for emitter
fireworksEmitter.particleColorSequence = nil
fireworksEmitter.particleColor = color
// Set number of particles
fireworksEmitter.particleBirthRate = particleBirthRate
fireworksEmitter.numParticlesToEmit = maxParticles
// Position at point
fireworksEmitter.position = skOverlayPoint
// Add to SpriteKit overlay
skOverlay.addChild(fireworksEmitter)
// Remove emitter, <animationDur> is only a rough estimate
let animationDur = 3 * Double(fireworksEmitter.particleLifetime + fireworksEmitter.particleLifetimeRange)
delay(animationDur) {
fireworksEmitter.removeFromParent()
}
}
}
func delay(_ delay:Double, closure:@escaping ()->()) {
DispatchQueue.main.asyncAfter(
deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}
> Thread 11 Queue : com.apple.scenekit.renderingQueue.SCNView0x121d8d570
> (serial)
> #0 0x000000019c710aac in SKCParticleManager::enumerateParticleSystems(void (SKCParticleSystem*)
> block_pointer) ()
> #1 0x000000019c723d74 in SKCParticleSystemNode::generateRenderData_Quads(SKCRenderInfo*) ()
> #2 0x000000019c7236c0 in SKCParticleSystemNode::addRenderOps_Quads(SKCRenderInfo*,
> std::__1::shared_ptr<jet_command_buffer> const&) ()
> #3 0x000000019c71dc4c in SKCRenderer::expandRenderGroup(std::__1::shared_ptr<SKCRenderSortGroup>
> const&, std::__1::shared_ptr<jet_command_buffer> const&) ()
> #4 0x000000019c71b238 in SKCRenderer::expandRenderPass(std::__1::shared_ptr<SKCRenderPass>
> const&, std::__1::shared_ptr<jet_command_buffer> const&) ()
> #5 0x000000019c71a888 in SKCRenderer::render(SKCNode*, float __vector(4), std::__1::shared_ptr<jet_framebuffer> const&, unsigned int __vector(4), simd_float4x4, bool, NSDictionary*, SKCStats*,
> SKCStats*, double) ()
> #6 0x000000019c6516a4 in -[SKSCNRenderer renderWithEncoder:pass:commandQueue:] ()
> #7 0x0000000199479fc8 in -[SCNRenderContextMetal renderSKSceneWithRenderer:overlay:atTime:] ()
> #8 0x0000000199525018 in -[SCNRenderer _drawOverlaySceneAtTime:] ()
> #9 0x00000001995e199c in __C3DEngineContextRenderPassInstance ()
> #10 0x00000001995e27cc in C3DEngineContextRenderMainTechnique ()
> #11 0x0000000199526508 in -[SCNRenderer _renderSceneWithEngineContext:sceneTime:] ()
> #12 0x0000000199526688 in -[SCNRenderer _drawSceneWithNewRenderer:] ()
> #13 0x0000000199526ccc in -[SCNRenderer _drawScene:] ()
> #14 0x0000000199527144 in -[SCNRenderer _drawAtTime:] ()
> #15 0x00000001995cfa74 in -[SCNView _drawAtTime:] ()
> #16 0x00000001994876c0 in __69-[NSObject(SCN_DisplayLinkExtensions) SCN_setupDisplayLinkWithQueue:]_block_invoke ()
> #17 0x000000019959700c in __36-[SCNDisplayLink _callbackWithTime:]_block_invoke ()
> #18 0x00000001042a12cc in _dispatch_call_block_and_release ()
> #19 0x00000001042a128c in _dispatch_client_callout ()
> #20 0x00000001042aff80 in _dispatch_queue_serial_drain ()
> #21 0x00000001042a47ec in _dispatch_queue_invoke ()
> #22 0x00000001042b0f6c in _dispatch_root_queue_drain_deferred_wlh ()
> #23 0x00000001042b8020 in _dispatch_workloop_worker_thread ()
> #24 0x00000001858a6f1c in _pthread_wqthread ()
It's hard to tell what's going on when viewing this function in isolation, but the crash stack trace line SKCParticleManager::enumerateParticleSystems(void (SKCParticleSystem*)
makes me suspect that the issue is related to the addition/removal of the particle emitters, possibly on a queue other than the main queue.
SKNode docs:
Manipulations to nodes must occur in the main thread.
I'd double check that the addChild
and removeFromParent
methods are being invoked only on the main queue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With