SceneKit load node with animation from separate sc

2019-04-10 04:51发布

I have a view that creates SCNView dynamically. It's scene is empty, but when I press a button I would like to add a node from separate scn file. This file contains animation, and I would like it to animate in main scene. The problem is that after adding object to the scene it's not animating. When I use this file as SCNView scene it works. isPlaying and loops are enabled. What else do I need to do to import such node with animation? Sample code below:

override func viewDidLoad() {
    super.viewDidLoad()

    let scene = SCNScene()
    let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    sceneView.scene = scene
    sceneView.loops = true
    sceneView.isPlaying = true
    sceneView.autoenablesDefaultLighting = true
    view.addSubview(sceneView)


    let subNodeScene = SCNScene(named: "Serah_Animated.scn")!
    let serah = subNodeScene.rootNode.childNode(withName: "main", recursively: false)!

    scene.rootNode.addChildNode(serah)


}

2条回答
forever°为你锁心
2楼-- · 2019-04-10 05:04

All you need is retrieving animations:

        [childNode enumerateChildNodesUsingBlock:^(SCNNode *child, BOOL *stop) {
        for(NSString *key in child.animationKeys) {               // for every animation key
            CAAnimation *animation = [child animationForKey:key]; // get the animation
            animation.usesSceneTimeBase = NO;                     // make it system time based
            animation.repeatCount = FLT_MAX;                      // make it repeat forever
            [child addAnimation:animation forKey:key];            // animations are copied upon addition, so we have to replace the previous animation
        }
    }];
查看更多
戒情不戒烟
3楼-- · 2019-04-10 05:22

You need to fetch the animation from your scene Serah_Animated.scn, which will be a CAAnimation object. You then add that animation object to the rootNode of your main scene.

let animScene = SCNSceneSource(url:<<URL to your scene file", options:<<Scene Loading Options>>)
let animation:CAAnimation = animScene.entryWithIdentifier(<<animID>>, withClass:CAAnimation.self)

You can find the animID from the .scn file using scene editor in Xcode, as shown below.

SceneKit AnimationID from the Xcode Scene Editor

Now you can add the animation object to your root node.

scene.rootNode.addAnimation(animation, forKey:<<animID>>)

Note that we are reusing animID, that will allow you to also remove the animation from the node.

scene.rootNode.removeAnimation(forKey:<<animId>>)
  • My solution above assumes your animation is a single animation. If you see a bunch of animations, you need to add all the animation nodes. In my workflow, I have files in Blender which I export to Collada format and then use the Automated Collada Converter to ensure I have single animation nodes.
  • Related SO answer
  • You can also fetch the animID programmatically using entriesWithIdentifiersOfClass(CAAnimation.self), useful when you have a bunch of animations instead of a single animation as above or if you just want to add the animation without bothering about the animID before hand.
  • Apple Sample Code for scene kit animations, note the sample code is in ObjC but translation to Swift should be straight forward.
查看更多
登录 后发表回答