SceneKit之Animation

SceneKit之Animation_第1张图片

Animation

我们来了解一下隐式动画、显式动画和操作,以及何时在应用程序中选择它们。

SceneKit的动画支持是基于核心动画Core Animation框架。

我们可以修改某个动画属性值来创建隐式动画,隐式动画的好处就是不需要编写大量动画代码。

SCNTransaction类为场景内容更改定义了SceneKit的体系结构,包括隐式动画:一个transaction是单条线程安全的操作,它组合了对节点、几何图形、材质或其他场景内容的多个更改。默认情况下,SceneKit会自动在运行循环中对场景所做的所有更改创建一个默认的transaction

默认的transaction的持续时间animationDuration为零,因此动画属性上的更改将立即发生。但是,如果增加transactionanimationDuration,则所有动画属性上的更改都会自动进行。例如,更改IBAction方法中的动画持续时间会导致该方法中的位置和不透明度同时更改。

@IBAction func fallAndFade(_ sender: Any) {
    SCNTransaction.animationDuration = 1.0
    textNode.position.y = -10
    textNode.opacity = 0
}

而对于更复杂的动画,可以创建一个显式动画对象并将其附加到正在进行动画的场景元素上。创建的动画对象还可以重用,可以在任何需要的时候播放相同的动画,或者将其应用于场景的不同元素,所以很方便啊。

我们想要创建一个动画时,不直接使用CAAnimation类,而是使用它的子类:CABasicAnimationCAKeyframeAnimationCAAnimationGroupCATransition,来创建动画对象,并设置它的属性值,然后附加到场景节点元素上。

let animation = CABasicAnimation(keyPath: "geometry.extrusionDepth")
animation.fromValue = 0.0
animation.toValue = 100.0
animation.duration = 1.0
animation.autoreverses = true
animation.repeatCount = .infinity
textNode.addAnimation(animation, forKey: "extrude")

SceneKit还使用CAAnimation对象来创建使用外部3D创作工具创建并保存在场景文件中的动画。例如,艺术家可能创建一个游戏角色,其中包含用于行走、跳跃和其他动作的动画。通过使用SCNSceneSource类从场景文件中加载动画对象并将其附加到表示游戏角色的SCNNode对象,可以将这些动画合并到游戏中。

SCNTransaction

上面有提到SCNTransaction这个类,它是一种创建隐式动画并将scene graph上的更改合并到线程安全atomic更新的机制。

SceneKit在您修改scene graph中的对象时自动创建一个事务transaction。此事务将在该线程的runloop循环的当前迭代期间对同一线程所做的任何其他更改进行分组。当运行循环下一次迭代时,SceneKit自动提交事务,原子性atomic地将事务期间所做的所有更改应用于当前显示的scene graph中。

因为自动事务的默认持续时间为零,所以当SceneKit自动提交事务时,它所包含的任何更改都会立即出现。通过使用setAnimationDuration(_:)方法来更改持续时间,您可以隐式地将事务期间对animatable属性所做的所有更改动画化。您可以使用隐式动画快速、轻松地将动画添加到场景中。例如,淡入并移动一个节点,淡入另一个节点,移动并缩放视图摄像机,并聚焦聚光灯,所有这些都在一个一秒钟的动画中完成。

[SCNTransaction setAnimationDuration:1.0];    
_textNode.position = SCNVector3Make(0.0, -10.0, 0.0);
_textNode.opacity = 0.0;
_heroNode.opacity = 1.0;
view.pointOfView = _heroCamera;
_heroCamera.camera.yFov = 20.0;
_lightNode.light.spotInnerAngle = 30.0;

您还可以使用SCNTransaction类方法来创建和管理您自己事务的层次结构。通过嵌套自定义事务,您可以对scene graph更改集进行分组,为每个组应用不同的动画参数。使用begin()方法创建一个自定义事务,如果存在,则嵌套在当前事务中。使用commit()方法结束事务,应用所有在其中进行的scene graph更改。

SCNAnimatable: Protocol

该协议提供了将动画附加到节点、几何图形、材质和其他SceneKit对象的常用接口。

SceneKit使用与核心动画框架相同的架构,允许您对属性进行隐式或显式的动画更改。对于隐式动画,使用SCNTransaction类可以用很少的代码快速创建简单的动画。对于更复杂的动画,显式地创建CAAnimation子类对象,并使用SCNAnimatable协议中的方法将它们附加到要动画的SceneKit对象。而且还可以使用此协议中的方法来控制已经附加到SceneKit对象的任何动画。

例如,下面创建一个使节点持续旋转的动画:

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
// Animate one complete revolution around the node's Y axis.
rotationAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
rotationAnimation.duration = 10.0; // One revolution in ten seconds.
rotationAnimation.repeatCount = FLT_MAX; // Repeat the animation forever.
[node addAnimation:rotationAnimation forKey:nil]; // Attach the animation to the node to start it.

你可能感兴趣的:(SceneKit之Animation)