如何在SCNNode中存储其他信息?

时间:2017-08-27 15:27:41

标签: ios swift scenekit arkit

我正在iOS 11(beta)上使用ARKit和SceneKit编写iOS应用程序。

此应用程序将许多项目添加到增强现实场景中。为了识别这些项目中的每一项,我将SCNNode子类化为MySCNNode并在其中放入id字段:

MySCNNode: SCNNode {
    var id: Int
    ...some initializer to assign value to the id
}

我还实现了touchesBegan委托方法。当用户触摸某个项目时,我想检索其对应的id。所以我尝试将该项目的相应SCNNode投回到MySCNNode

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

    // hitTest to retrieve item's id
    if let touchLocation = touches.first?.location(in: sceneLocationView) {
        DDLogDebug("received touch location")
        if let hit = sceneLocationView.hitTest(touchLocation, options: nil).first {
            DDLogDebug("received a hit")
            if let scnNode = hit.node as? SCNNode {
                DDLogDebug("received a scnNode)")
                    if let mySCNNode = scnNode as? MySCNNode {
                        DDLogDebug("received a MySCNNode") // ====> Never reaches here
                    }

            }


            return
        }


    }


}

但是,从SCNNode投射到MySCNNode的步骤永远不会发生

在上面的点击测试中尝试将SCNNode强制转换为MySCNNode时,我写错了吗?有没有其他方法可以在SCNNode中存储其他信息并在以后检索它?

谢谢

2 个答案:

答案 0 :(得分:2)

首先,您不需要id。相反,您可以使用现有的name属性。但是,如果要检查节点类型,还应该检查它的父节点,因为hitTest结果节点从子节点开始。您可以添加SCNNode扩展名:

extension SCNNode {
    /// Returns parent node of specified type.
    ///
    /// - Returns: An optional `SCNNode` of specified `T` class type.
    func parentOfType<T: SCNNode>() -> T? {
        var node: SCNNode! = self
        repeat {
            if let node = node as? T { return node }
            node = node?.parent
        } while node != nil
        return nil
    }
}

然后使用:

if let myNode = node.parentOfType() as? MySCNNode {
    // do something
}

答案 1 :(得分:0)

我认为你走在正确的轨道上,但你不需要这么多的演员阵容,如果你“堆叠”if let,它会更容易。试试这个:

if let touchLocation = touches.first?.location(in: sceneLocationView),
    let hit = sceneLocationView.hitTest(touchLocation, options: nil).first,
    let myNode = hit.node as? MySCNNode {
    DDLogDebug("received a MySCNNode")
}