SceneKit:在 SCNView 上渲染 SpriteKit 粒子系统时应用程序崩溃,当所有代码似乎都是系统代码的一部分时如何调试
Posted
技术标签:
【中文标题】SceneKit:在 SCNView 上渲染 SpriteKit 粒子系统时应用程序崩溃,当所有代码似乎都是系统代码的一部分时如何调试【英文标题】:SceneKit: app crashes when rendering SpriteKit particle system over SCNView, how to debug when all code seems to be part of system code 【发布时间】:2018-09-01 19:44:58 【问题描述】:在SCNView
的overlaySKScene
属性中运行SpriteKit
粒子系统会导致应用崩溃,并显示下面的堆栈跟踪。
根据堆栈跟踪,似乎所有系统代码都在运行,那么您应该如何调试崩溃,更重要的是,确定它是 SceneKit/SpriteKit 的错误还是应用程序中的错误?
不管怎样,下面是添加粒子系统的函数,但堆栈跟踪中没有引用它。
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 ()
【问题讨论】:
我喜欢你的名字非常适合这篇文章。 【参考方案1】:单独查看此函数时很难判断发生了什么,但崩溃堆栈跟踪行 SKCParticleManager::enumerateParticleSystems(void (SKCParticleSystem*)
让我怀疑该问题与粒子发射器的添加/删除有关,可能在队列之外主队列。
SKNode docs:
对节点的操作必须发生在主线程中。
我会仔细检查 addChild
和 removeFromParent
方法是否仅在主队列上被调用。
【讨论】:
有趣的想法!这是发射器被移除的唯一地方,你是说在delay
函数中代码可能被从主队列中调用吗?
我说不清楚。 delay
是如何实现的? animateFireworks
可以从主队列中调用吗?
刚刚添加了delay
的代码。 animateFireworks
仅在用户点击屏幕时调用。谢谢!
看起来延迟只会在主队列上调度。我会尝试分别评论 addChild
和 removeFromParent
以缩小导致问题的范围。以上是关于SceneKit:在 SCNView 上渲染 SpriteKit 粒子系统时应用程序崩溃,当所有代码似乎都是系统代码的一部分时如何调试的主要内容,如果未能解决你的问题,请参考以下文章
ARMeshAnchor – SceneKit SCNView 渲染器 EXC_BAD_ACCESS
SceneKit开发教程02 SCNScene和SCNView
DefaultCameraController 上的 SceneKit 动画
iOS 12 中autoenablesDefaultLighting 太亮,SCNView.pointOfView 无效