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

在SceneKit游戏中为SCNNode设置SCNConstraint(LookAt)动画,以使过渡逐渐进行

  •  1
  • Manganese  · 技术社区  · 7 年前

    一般来说,当你想让游戏中的角色面对镜头时,可以使用SCNLookAtConstraint,这实际上也很适合我。

    在下面 my\u对象 是我尝试根据约束定向的节点。”“敌人”是指场景中的某个节点,而“视点”是指场景的视点。当我点击我的\u对象时,它应该看敌人一秒钟,然后回到我的角度。

    设置LookAtConstraint,使“对象”注视“敌人”一秒钟。

    my_object.constraints?.removeAll()
    let targetNode = sceneView.scene.rootNode.childNode(withName: (chosenScenarioForChallenge?.shape)!, recursively: true)
    let lookAt = SCNLookAtConstraint(target: targetNode)
    lookAt.isGimbalLockEnabled = true
    my_object.constraints = [lookAt]                    
    Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(resetObject), userInfo: nil, repeats: false)
    

    在查看“敌人”节点后重置对象以查看我的视角

    @objc
    func resetObject() {
        my_object.constraints?.removeAll()
        let targetNode = sceneView.pointOfView
        let lookAt = SCNLookAtConstraint(target: targetNode)
        lookAt.isGimbalLockEnabled = true
        my_object.constraints = [lookAt]
        }
    

    我的问题是,我不希望约束的变化是突然的。我希望它是平滑的,因此我想把动画融入其中。在查看了SCNAction和SCNAnimation之后,我没有找到任何与约束相关的内容。由于约束会动态更新位置,我可以理解操作。移动(到/通过:)等将不起作用。最终,当我轻触时,我的对象应该开始逐渐观察敌人的节点,1-2秒后,它应该回来观察我的视角,这太过缓慢了。

    请注意,我不希望角色从技术上看向相机,因此我使用的是SCNLookAtConstraint,而不是SCNBillboardConstraint。

    指点会很有帮助的,蒂亚。

    3 回复  |  直到 7 年前
        1
  •  4
  •   mnuages    7 年前

    这个 target 属性是读写的,因此您应该能够重用 SCNLookAtConstraint 实例(而不是创建一个新实例)并交换目标。

    编辑

    这个 influenceFactor 对于约束,可以在节点的当前变换和约束计算的变换之间创建更平滑的动画。

        2
  •  1
  •   LukeSideWalker    5 年前

    根据测试@Managanese的答案,我可以说 它起作用了 ,不知怎的 影响因素 以及 动画持续时间 携手合作。我真的不明白,为什么 影响因素 是必要的,它应该在没有的情况下工作,但不知何故,它是必要的。

    我为其他正在解决此问题的人展示了一个代码示例( Swift 5.0,Xcode 11.2 ):

    private func smoothlyLookAtTarget() {
    
        // influenceFactor and animationDuration work somehow together
    
        let constraint = SCNLookAtConstraint(target: targetNode)
        constraint.isGimbalLockEnabled = true
        constraint.influenceFactor = 0.1
    
        SCNTransaction.begin()
        SCNTransaction.animationDuration = 3.0
        cameraNode.constraints = [constraint]
        SCNTransaction.commit()
    }
    
        3
  •  0
  •   leerie simpson    4 年前

    另一种方法是使用look约束将摄影机锁定到cameraTargetNode,然后通过动画移动该节点,甚至在该节点上设置约束以保持与目标的距离或复制目标。位置通过这种方式,可以将摄影机约束上的影响一次性设置为合适的福吉值。相机在其整个生命周期中保持其约束,您可以随意启用/禁用它。

    这种方法的另一个好处是调试。您可以在开发过程中为cameraTargetNode提供您选择的几何体,并跟踪摄影机目标,而无需推断或感觉实际目标是什么。

    我更进一步,使用cameraMovementNode,在cameraNode上设置距离和加速度约束,以便查看外观和移动节点的位置。“影响因子”(Influence factor)和“isEnabled”(isEnabled)在这里也很有用,因为您可以调整影响或禁用约束,而不影响约束目标。有时我注意到,设置目标、更改/设置约束,甚至将相机移入和移出树形图,都会导致奇怪的旋转和旋转。

    使用我的方法,您可以将外观或目标移动到场景中的其他孩子,而不会有任何奇怪的行为。通过这种方式,您可以通过操作/事务移动moveMode,完成后,将其添加为目标的子级,并获得目标的跟随和旋转。此外,reset()可以清除这些摄影机辅助节点的约束,并根据需要将其移动到场景的根。