Make an object orbit different in SceneKit
Let's say I have 2 nodes in my SceneKit. I want it to rotate around or in orbit (like a planet orbiting a star), another node once in a certain amount of time. I know I can customize the animation like this:
let anim = CABasicAnimation(keyPath: "rotation")
anim.fromValue = NSValue(scnVector4: SCNVector4(x: 0, y: 1, z: 0, w: 0))
anim.toValue = NSValue(scnVector4: SCNVector4(x: 0, y: 1, z: 0, w: Float(2 * Double.pi)))
anim.duration = 60
anim.repeatCount = .infinity
parentNode.addAnimation(aim, forKey: "spin around")
Is there an animation for the "orbit" and a way to indicate the target of the node?
source to share
The way to do this is to use an additional (auxiliary) SCNNode. You will be taking advantage of the fact that it adds its own coordinate system and that all of its child nodes will move with this (auxiliary) coordinate system. Child nodes that are off-center will rotate effectively if you view them from the world coordinate system.
-
You add the HelperNode at the center of your FixedPlanetNode (orbiting planet), possibly as a child of it, but definitely in the same position
-
You add your OrbitingPlanetNode as a child to the HelperNode , but with an offset on one of the axes, for example. 10 points on the X-axis
-
You start rotating the HelperNode (along with its coordinate system) around an axis, eg. Y axis
-
This will cause the OrbitingPlanetNode to rotate around the Y-axis of the HelperNode with an orbit radius of 10 points.
Example
earthNode
- fixed orbiting planet
moonNode
- orbiting planet
helperNode
- helper node added to provide coordinate system
// assuming all planet geometry is at the centre of corresponding nodes
// also helperNode.position is set to (0, 0, 0)
[earthNode addChildNode:helperNode];
moonNode.position = SCNVector3Make(10, 0, 0);
[helperNode addChildNode:moonNode];
// set helperNode to rotate forever
SCNAction * rotation = [SCNAction rotateByX:0 y:3 z:0];
SCNAction * infiniteRotation = [SCNAction repeatActionForever:rotation];
[helperNode runAction:infiniteRotation];
I have used actions and objective-c since this is what I am familiar with, but should be done fine in Swift and with animations.
source to share