代码之家  ›  专栏  ›  技术社区  ›  JuJoDi

节点组的位置在SCNNode.runAction开始时重置

  •  0
  • JuJoDi  · 技术社区  · 9 年前

    我有一些代码,当屏幕按如下方式敲击时,可以围绕x轴旋转几个SCNNode:

    func handleTap(gestureRecognize: UIGestureRecognizer) {
        let sceneView = self.view as SCNView
    
        let slice = self.cubes[0...8]
        let container = SCNNode()
        for node: SCNNode in slice {
            container.addChildNode(node)
        }
        sceneView.scene!.rootNode.addChildNode(container)
        container.runAction(SCNAction.rotateByX(CGFloat(M_PI / 2), y: 0.0, z: 0.0, duration: 1), completionHandler: { () -> Void in
            println("complete")
        })
    }
    

    我遇到的问题是,每次调用此函数时,节点似乎都会在执行操作之前将自己重置到原始位置。当操作完成时,它们似乎停留在正确的位置,直到再次点击屏幕。如何拨打后续电话 handleTap 将其从当前位置旋转?

    在将节点添加到容器之前,我已经尝试从它们的原始父节点中删除这些节点,但没有明显的效果。

    我也尝试过使用动画

        let spin = CABasicAnimation(keyPath: "rotation")
        spin.fromValue = NSValue(SCNVector4: SCNVector4(x: -1, y: 0, z: 0, w: 0))
        spin.toValue = NSValue(SCNVector4: SCNVector4(x: -1, y: 0, z: 0, w: Float(M_PI_2)))
        spin.duration = 3
        spin.repeatCount = .infinity
        container.addAnimation(spin, forKey: "spin around")
    

    这与行动的效果完全相同。

    如果我将节点作为根视图的子级放回runAction的完整块中

        container.runAction(action, completionHandler: { () -> Void in
            println("completed rotation")
            for node: SCNNode in slice {
                node.removeFromParentNode()
                sceneView.scene!.rootNode.addChildNode(node)
            }
        })
    

    然后,在动作完成时,节点将返回到其原始位置,而不是在新敲击开始时。

    2 回复  |  直到 9 年前
        1
  •  0
  •   JuJoDi    9 年前

    当节点从场景的根节点中移除、添加到容器并旋转时,相对于容器的局部坐标系将变换应用于节点。解决方案是将节点的变换从容器的坐标系转换为根节点的坐标系,然后再将其添加回根节点。

    func handleTap(gestureRecognize: UIGestureRecognizer) {
        let sceneView = self.view as SCNView
        let action = SCNAction.rotateByAngle(CGFloat(M_PI_2), aroundAxis: SCNVector3Make(-1, 0, 0), duration: 1)
        let slice = self.cubes[0...8]
        let container = SCNNode()
        let root = sceneView.scene!.rootNode
    
    
        for node: SCNNode in slice {
            container.addChildNode(node)
        }
    
        root.addChildNode(container)
    
        container.runAction(action, completionHandler: { () -> Void in
            for node: SCNNode in slice {
                let transform = node.parentNode!.convertTransform(node.transform, toNode: root)
                node.removeFromParentNode()
                node.transform = transform
                root.addChildNode(node)
            }
        })
    }
    
        2
  •  0
  •   luismgb    5 年前

    这是我旋转 SCNNode 没有容器或类似的东西:

    let targetRotationRadians: CGFloat = targetRotationAngle * (CGFloat.pi / 180.0)
    let rotationAction = SCNAction.rotateTo(x: 0.0, y: targetRotationRadians, z: 0.0, duration: animationDuration, usesShortestUnitArc: true)
    yourSCNNode.runAction(rotationAction)
    

    重要的是设定 usesShortestUnitArc true 在中 SCNAction.rotateTo 方法这样,节点在旋转到所需角度之前不必返回到其原始角度。