how to track the position of a node after applying

2019-08-14 14:33发布

As soon as a node starts moving, for some reason, it stops tracking the position of the node. and here's what I mean:

 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)

}

The Node is moving, which is great, but I'd like to track the current position of the node while it's moving:

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

None of these properties is updating the location, so I know I'm missing something. I'd like to stop it from moving when it gets to a certain position (in y coordinate). If anyone had a success tracking the location of a node after .applyForce, I'd much appreciate it if you could point out what I did wrong, and perhaps what worked for you. thanks.

UPDATE

Here's some code I'm using to test it.

I'm declaring the node at the beginning of this ViewController:

var currNode = SCNNode()

You can try the following for testing to track the location of a node with the ARKit default project:

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

标签: swift arkit
1条回答
太酷不给撩
2楼-- · 2019-08-14 15:19

So Answer of your question is in one line

use node.presentation property

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

From Apple Docs

When you use implicit animation (see SCNTransaction) to change a node’s properties, those node properties are set immediately to their target values, even though the animated node content appears to transition from the old property values to the new. During the animation SceneKit maintains a copy of the node, called the presentation node, whose properties reflect the transitory values determined by any in-flight animations currently affecting the node.

Hope it is helpful

查看更多
登录 后发表回答