2017-08-27 58 views
1

我正在iOS 11(beta)上使用ARKit和SceneKit編寫iOS應用程序。如何在SCNNode中存儲附加信息?

此應用程序將許多項目添加到增強現實場景中。爲了識別這些項目,我子類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 
     } 


    } 


} 

然而,步投從SCNNodeMySCNNode從未發生過

難道我寫了一些不對的地方嘗試投放的SCNNode回MySCNNode時在上面的命中測試?有沒有其他方法可以將附加信息存儲在SCNNode中,然後再檢索它?

謝謝

+0

「爲了確定每個項目的」使用場景視圖中的name屬性。 –

回答

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") 
} 
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 
}