我在SCNode命中检测方面遇到了一些麻烦.我需要检测在具有SCNNode的场景中触摸了哪个对象,我已经实现了这段代码但是当我触摸对象时它似乎崩溃但是当我触摸其余的sceneView时工作正常.
override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) { let touch = touches.first as! UITouch if(touch.view == self.sceneView){ print("touch working") let viewTouchLocation:CGPoint = touch.location(in: sceneView) guard let result = sceneView.hitTest(viewTouchLocation,options: nil).first else { return } if (bottleNode?.contains(result.node))! { //bottleNode is declared as SCNNode? and it's crashing here print("match") } } }
这里存在多个问题,现有的答案只涉及其中的一些问题.
>从您发布的代码中可以清楚地知道,当此方法运行时,bottleNode是否可以为nil.当值为nil时,通过可选(?in bottle?.contains)调用方法将无声地失败 – 导致整个表达式结果包含在一个Optional中,其值为nil – 但是你有一个parens和一个强制解包的力量整个表达式,所以nil-unwrap会崩溃.
> contains(_ :)不是SCNNode上的方法.目前还不清楚你的bottleNode是什么类型的,你甚至可以编写这个方法调用而不会出现编译器错误…但是如果bottleNode实际上是一个SCNNode并且你已经做了一些类型擦除/任意转换goop以允许调用编译,由于不存在的方法,调用将在运行时失败.
如果你使用bottleNode.contains行的目标是确定命中测试结果是bottleNode本身还是其子节点,我建议定义和使用这样的扩展方法:
extension SCNNode { func hasAncestor(_ node: SCNNode) -> Bool { if self === node { return true // this is the node you're looking for } if self.parent == nil { return false // target node can't be a parent/ancestor if we have no parent } if self.parent === node { return true // target node is this node's direct parent } // otherwise recurse to check parent's parent and so on return self.parent.hasAncestor(node) } } // in your touchesBegan method... if let bottleNode = bottleNode,result.node.hasAncestor(bottleNode) { print("match") }
相反,您的目标是确定result.node是否位于bottleNode的边界框内或与其重叠(无论节点层次结构如何),回答该问题会稍微复杂一些. boundingSphere检查中的一个简单位置非常简单,或者如果您正在寻找包含/重叠,octree可能会有所帮助.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。