'SceneKit: How to constrain movement of a node to one axis locally, not the entire world
It's very easy to prevent movement of a node in one axis (X, Y, or Z) being moved by other forces with an SCNTransformConstraint.positionConstraint in world space as follows:
let zPosition = node.position.z
let strafingConstraint = SCNTransformConstraint.positionConstraint(inWorldSpace: true, with: {(_ node: SCNNode, _ position: SCNVector3) -> SCNVector3 in
localPosition = position
localPosition.z = zPosition
return localPosition
})
node.constraints = [strafingConstraint];
However, this constrains this in world space. What do I do if I want to just make the node no longer move in its local Z axis, regardless of its orientation, so it can only move in its local X and Y axes, what do I do? Is there a way to use the .convertPosition(:from:) or .convertPosition(:to:) functions to do this? Is there a better way?
Solution 1:[1]
This might be an alternative approach to fix a node to a specific axis without using a SCNConstraint.
Use the updateAtTime
delegate function to adjust the z-position of your node within each frame:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
node.position.z = 0.0 // or wherever you want to have it
}
(If your node has a physics body attached to it, you should only alter it's position when the body type is = .kinematc
)
Solution 2:[2]
With this constraint myNode only moves along the x and y axes and is constrained to zPosition along the z axis:
let zAxisConstraint = SCNTransformConstraint.positionConstraint(inWorldSpace: true) { node, position
in
let newPosition = SCNVector3(position.x, position.y, zPosition)
return newPosition
}
myNode.constraints = [zAxisConstraint]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ZAY |
Solution 2 | Paul Broderick |