首页 文章

如何在Arkit 1.5中施加力后跟踪节点的位置

提问于
浏览
1

一旦节点开始移动,由于某种原因,它就会停止跟踪节点的位置 . 这就是我的意思:

internal func launchNode(force:Float) {
    let force = force * 0.004

    currNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
    currNode.physicsBody?.mass = 0.05

    let direction = currNode.worldFront + SCNVector3(force, -force, -force)
    currNode.physicsBody?.applyForce(direction, asImpulse: true)

}

Node正在移动,这很棒,但我想跟踪节点移动时的当前位置:

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {

guard currNode != nil else { return }

    print("simdWorldPosition: \(currNode.simdWorldPosition.y)  position: \(currNode.position.y) simWorldPosition: \(currNode.simdWorldPosition.y)  simPosition: \(currNode.simdPosition.y)")
}

这些属性都没有更新位置,所以我知道我遗漏了一些东西 . 当它到达某个位置时(y坐标),我想阻止它移动 . 如果有人在.applyForce之后成功跟踪节点的位置,我会非常感激,如果你能指出我做错了什么,也许对你有用 . 谢谢 .

UPDATE

这是我用来测试它的一些代码 .

我在这个ViewController的开头声明了节点:

var currNode = SCNNode()

您可以尝试以下测试来跟踪ARKit默认项目的节点位置:

//call this once your scene is set
func addTapGestureToSceneView() {
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.didTap(withGestureRecognizer:)))
    sceneView.addGestureRecognizer(tapGestureRecognizer)
}

@objc func didTap(withGestureRecognizer recognizer: UIGestureRecognizer) {
    let tapLocation = recognizer.location(in: sceneView)
    let hitTestResults = sceneView.hitTest(tapLocation)
    guard let node = hitTestResults.first?.node else { return }
    if node.name == "shipMesh" {
        currNode = node
        moveShip()
    }
}

  internal func moveShip() {
    let force = 2 * 0.004
    currNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
    currNode.physicsBody?.mass = 0.05
    let direction = currNode.worldFront + SCNVector3(force, -force, -force)
    currNode.physicsBody?.applyForce(direction, asImpulse: true)

}

  func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {

    print("simdWorldPosition: \(currNode.simdWorldPosition.y)  position: \(currNode.position.y) simWorldPosition: \(currNode.simdWorldPosition.y)  simPosition: \(currNode.simdPosition.y)")
}

1 回答

  • 0

    所以你的问题的答案是一行的

    使用 node.presentation 属性

    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    
        print("simdWorldPosition: \(currNode.presentation.simdWorldPosition.y)  position: \(currNode.presentation.position.y) simWorldPosition: \(currNode.presentation.simdWorldPosition.y)  simPosition: \(currNode.presentation.simdPosition.y)")
    }
    

    来自Apple Docs

    当您使用隐式动画(见SCNTransaction)更改节点的属性,这些节点属性将立即设置为它们的目标值,即使动画节点内容似乎从旧的属性值到新的过渡 . 在动画期间,SceneKit维护一个节点的副本,称为表示节点,其属性反映由当前影响节点的任何正在进行的动画确定的暂时值 .

    希望它有所帮助

相关问题