在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃

Posted

技术标签:

【中文标题】在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃【英文标题】:Removing SCNNode nodes from scene.rootNode is causing a crash, in SceneKit 【发布时间】:2018-10-07 16:47:37 【问题描述】:

我正在尝试从我的场景中删除一组代表路径的节点。它们是使用 SCNGeometrySource 和 SCNGeometryElement 创建的 SCNSphere 几何节点和自定义几何表示线的组合。

我不会在任何类型的数组中保留这些节点。相反,我在场景中 rootNode 的节点树的第一级搜索这些节点,按它们的名称,然后调用一个使它们淡出的动作序列,并且它们应该从根节点中删除自己。

代码如下:

func clearPath() 
    //
    let disappear = SCNAction.fadeOut(duration: 0.1)
    let remove = SCNAction.removeFromParentNode()
    let sequence = SCNAction.sequence([disappear, remove])

    if let pathNodesToRemove = pathNodes() 
        //
        for node in pathNodesToRemove 
            //
            node.removeAllActions()
            node.runAction(sequence)
        
    

    if let lineNodesToRemove = lineNodes() 
        for node in lineNodesToRemove 
            //
            node.removeAllActions()
            node.runAction(sequence)
        
    

    path.removeAll()

地点:

func pathNodes() -> [SCNNode]? 
    //

...        

    let nodes = rootNode.childNodes.filter  (node) -> Bool in
        //
        guard let name = node.name else  return false 
        if name.hasPrefix(configurationComponent.id) &&
            name.range(of:"_PATH") != nil 
            return true
         else 
            return false
        
    

    return nodes

lineNodes()函数基本相同。

我打开 Zombie Objects 以跟踪错误的来源,但我总是得到相同的错误:对 SceneKit`C3DNodeRemoveFromParentNode 的引用作为线程上调用的最后一件事,以及 EXC_BAD_ACCESS(代码=1,地址... )。

clearPath() 函数是整个应用程序中我调用“RemoveFromParentNode”的唯一位置。

节点上没有物理实体,也没有保留在其他任何地方。

关于如何解决这个问题的任何想法?

28/4/18 编辑:

这里是它发生的线程的崩溃报告。似乎 removeObjectFromChildNodesAtIndex 被调用了两次......

    Thread 9 name:  Dispatch queue: com.apple.scenekit.renderingQueue.Air_Relay.ARTCSCNView0x104126720
Thread 9 Crashed:
0   SceneKit                        0x00000001957d668c C3DNodeRemoveFromParentNode + 40
1   SceneKit                        0x0000000195826e28 -[SCNNode __removeObjectFromChildNodesAtIndex:] + 184
2   SceneKit                        0x0000000195826e28 -[SCNNode __removeObjectFromChildNodesAtIndex:] + 184
3   SceneKit                        0x0000000195827350 -[SCNNode removeFromParentNode] + 396
4   SceneKit                        0x000000019593e9fc -[SCNActionRemove updateWithTarget:forTime:] + 92
5   SceneKit                        0x0000000195907cb8 SCNCActionSequence::cpp_updateWithTargetForTime+ 2202808 (SCNNode*, double) + 316
6   SceneKit                        0x00000001957bcfb0 SCNActionApply + 112
7   SceneKit                        0x0000000195853d2c _applyActions + 236
8   CoreFoundation                  0x00000001814dccbc __CFDictionaryApplyFunction_block_invoke + 24
9   CoreFoundation                  0x00000001814c3f98 CFBasicHashApply + 132
10  CoreFoundation                  0x00000001814cdb64 CFDictionaryApplyFunction + 288
11  SceneKit                        0x0000000195853b5c C3DAnimationManagerApplyActions + 92
12  SceneKit                        0x000000019583b054 -[SCNRenderer _update:] + 656
13  SceneKit                        0x000000019583d018 -[SCNRenderer _drawSceneWithNewRenderer:] + 252
14  SceneKit                        0x000000019583d69c -[SCNRenderer _drawScene:] + 84
15  SceneKit                        0x000000019583daa0 -[SCNRenderer _drawAtTime:] + 728
16  SceneKit                        0x00000001958e446c -[SCNView _drawAtTime:] + 512

编辑 30/04/18

我继续向应用程序添加其他功能,我需要使用 SCNAction.removeFromParentNode() 删除节点。我也隔离了这些,以独立于上述代码引起问题。

随着每个新节点的生成,这些在 SCNRendererDelegate 更新中被更频繁地调用。

我还尝试使用 SCNAction.run 块直接在节点上使用 removeFromParentNode() ,并且发生了同样的问题。

【问题讨论】:

如果我有一个保留周期,即使它们没有存储在数组中,我也会在 removeNodes 上崩溃。尝试在 Leaks 中检查您的参考计数。 pathNodes() 和 lineNodes() 是否有可能返回一个公共节点? path.removeAll() 有什么作用? (clearPath 方法的最后一行) 【参考方案1】:

当您使用 SCNAction.removeFromParentNode() 时,您并没有删除节点,您必须删除它自己的节点。如果您删除路径或操作,您实际上是在创建一个 nil 值,因此当调用路径或操作时,现在有一个 nil 值并且它崩溃了。

【讨论】:

以上是关于在 SceneKit 中,从 scene.rootNode 中删除 SCNNode 节点会导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

从 Scenekit 中的世界变换中提取旋转

如何从代码在 SceneKit 中设置基于物理的渲染?

如何使用 SceneKit 从 COLLADA (.dae) 文件中获取几何图形

从 SceneKit 中的 SCNGeometry 中提取人脸信息

如何从 SCNVector3 在 SceneKit 中生成凹面或凸面多边形平面

SceneKit + Collada + 动画