LinusG.
LinusG.

Reputation: 28912

Animate SCNNode forever - SceneKit, Swift

I want to animate 2 cubes forever, until the user taps one of it. The animation is supposed to be like an ∞.

These are my cubes in the sceneView I want to animate: cubes to be animated

I am trying to do that with nested animations and it does partially work. Now, since the animations always wait until they're finished before starting the new one, it does not look smooth at all.

Before continuing to develop the ∞-animation I would like to know if there is a better (and actually working) way. This is my current code:

SCNTransaction.begin()
SCNTransaction.setAnimationDuration(2)
cube1.position = SCNVector3Make(3, 0, 0)
cube2.position = SCNVector3Make(-3, 0, 0)
println("log 0")
SCNTransaction.setCompletionBlock {
    println("log 1")
    while (animationKey != 1) {
        //initially animationKey = 0
        SCNTransaction.begin()
        SCNTransaction.setAnimationDuration(2)
        cube1.position.x += 1
        cube1.position.y += 1
        cube2.position.x += 1
        cube2.position.y += 1
        println("log 2")
        SCNTransaction.setCompletionBlock {
            SCNTransaction.begin()
            SCNTransaction.setAnimationDuration(2)
            cube1.position.x -= 1
            cube1.position.y -= 1
            cube2.position.x -= 1
            cube2.position.y -= 1
            println("log 3")
            SCNTransaction.setCompletionBlock { animationKey = 1 }
            SCNTransaction.commit()
        }
        println("log 4")
        SCNTransaction.commit()
        }
    }
    println("log 5")
    SCNTransaction.commit()
    println("log 6")
}

The output shows the following things: log 0, log 5, log 6, log 1, log 2, log 4, log 2...and then it just continues with log 4 and log 2 alternating.

Can someone help me there?

Note

Upvotes: 13

Views: 10149

Answers (2)

Konrad Wright
Konrad Wright

Reputation: 1264

If you're going to animate a SCNNode have your nodes run a SCNAction.

Swift:

let moveUp = SCNAction.moveBy(x: 0, y: 1, z: 0, duration: 1)
moveUp.timingMode = .easeInEaseOut;
let moveDown = SCNAction.moveBy(x: 0, y: -1, z: 0, duration: 1)
moveDown.timingMode = .easeInEaseOut;
let moveSequence = SCNAction.sequence([moveUp,moveDown])
let moveLoop = SCNAction.repeatForever(moveSequence)
myNode.runAction(moveLoop)

Objective-C:

SCNAction *moveUp = [SCNAction moveByX:0 Y:1 Z:0 duration:1];
moveUp.timingMode = SCNActionTimingModeEaseInEaseOut;
SCNAction *moveDown = [SCNAction moveByX:0 Y:-1 Z:0 duration:1];
moveDown.timingMode = SCNActionTimingModeEaseInEaseOut;
SCNAction *moveSequence = [SCNAction sequence:@[moveUp,moveDown]];
SCNAction *moveLoop = [SCNAction repeatActionForever:moveSequence];
[myNode runAction:moveLoop];

The code above will animate myNode up and down forever.

Upvotes: 37

mnuages
mnuages

Reputation: 13462

you can create a CAKeyframeAnimation animation from a Bezier path (see the path property). That way you will get a very smooth animation.

For it to repeat forever set its repeatCount to HUGE_VALF, and you can adjust the velocity using the timingFunction property.

Upvotes: 4

Related Questions