ARKit SceneKit かわいいアニメーション・レシピ・ブック

###ジャンプ
![Apr-09-2021 13-58-40.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/232d0010-cf07-2e48-d6ed-12abea45d164.gif)


```swift
extension SCNNode {
    func jump(duration:Double){
        let up = SCNAction.move(by: SCNVector3(0, 1, 0), duration: duration)
        let down = SCNAction.move(by: SCNVector3(0, -1, 0), duration: duration/2)
        self.runAction(SCNAction.repeatForever(SCNAction.sequence([up,down,SCNAction.wait(duration: duration)])))
    }
}
```


###いきおいあまったジャンプ
反動を小さなmoveとしてシーケンスで。

![Apr-08-2021 11-40-24.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/9d7aa92d-e998-e9a1-14a2-e10625e06e2f.gif)


```swift
extension SCNNode {
    func popin(){
        let popup = SCNAction.move(by: SCNVector3(0, 2.25, 0), duration: 0.6)
        let down = SCNAction.move(by: SCNVector3(0, -0.3, 0), duration: 0.2)
        let up = SCNAction.move(by: SCNVector3(0, 0.1, 0), duration: 0.2)
        let down1 = SCNAction.move(by: SCNVector3(0, -0.15, 0), duration: 0.2)
        down.timingMode = .easeOut
        up.timingMode = .easeIn
        down1.timingMode = .easeOut

        let pop = SCNAction.sequence([popup,down,up,down1])
        self.runAction(pop)
    }
}
```

###くるくる
永遠リピートで回し続ける。
durationを上げると速度が上がります。
![Apr-09-2021 13-53-55.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/594c78a6-a506-a5e1-b030-e04914ab0b08.gif)

```swift
extension SCNNode { 
    func rotate(duration:Double) {
        let rotate = SCNAction.rotateBy(x: 0, y: 6.28, z: 0, duration: duration)
        self.runAction(SCNAction.repeatForever(rotate))
    }
}
```

###sceneを回転させる
SCNSceneのrootNodeをSceneViewのrootNodeにaddChildNodeして、回転アニメーションをつけると、sceneが回転しているように見えます。

こういうシーンを回転させると
![スクリーンショット 2021-04-12 13.38.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/3ed580e5-b510-5ad0-1f8d-4c096821eeca.png)


![Apr-12-2021 13-37-48.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4fd8c67b-f331-2251-fa8b-f9542974a1b1.gif)

ライトミスってますごめんなさい。

```swift
let worldNode = SCNScene(named: "art.scnassets/world.scn")!.rootNode
sceneView.scene.rootNode.addChildNode(worldNode)
worldNode.position = SCNVector3(0, -1.5, 0)
worldNode.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 3)))
```

###しっぽふりふり
回転軸用のノードをかませると、geometry の中心以外でも回転させられます。
アクション回数を指定できます。

![Apr-12-2021 16-25-55.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/56161c32-70f1-5993-dc95-e47624078138.gif)


```swift
let dogTale = SCNNode() // 回転の中心となる、空のノード
dogTale.addChildNode(actualTale)
actualeTale.position = SCNVector3(0,0.3,0) // 実際の尻尾の位置をずらす
let taleFurifuri = SCNAction.repeat(SCNAction.sequence([ SCNAction.rotateTo(x: 0.5, y: 0, z: 0.7, duration: 0.05),SCNAction.rotateTo(x: 0.5, y: 0, z: -0.7, duration: 0.05)]),count: 16)
dogTale.runAction(taleFurifuri)
```

オブジェクトの中心の回転と、回転軸をずらす場合を同時に表示するとこういうイメージです。

![Apr-12-2021 16-40-10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c2a27d7a-2d65-f0f7-2aa8-b87c2bf9ebd4.gif)


```swift
// 軸をずらしたやーつ
let empty = SCNNode()
empty.addChildNode(dog)
dog.position = SCNVector3(0, 0.7, 0)
empty.position = SCNVector3(0, 0, -2)

// 中心で回るやーつ
let centerDog = dog.clone()
centerDog.position = SCNVector3(0, 0, -2)

sceneView.scene.rootNode.addChildNode(empty)
sceneView.scene.rootNode.addChildNode(centerDog)
empty.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 0.5)))
centerDog.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 0.5)))

```

###変身

isHiddenを入れ替えると、変化してるっぽく見えます。
変身アニメーションの完了ハンドラーの中でさりげなく変化させると、ぽく見えませんか？
ちなみに、回転と移動を同時に呼ぶこともできます。

![Apr-12-2021 15-04-59.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/aa6dc1dc-0241-13d7-0e63-598e917078aa.gif)


```swift
fox.runAction(SCNAction.sequence([SCNAction.move(by: SCNVector3(x: 0, y: 1.5, z: 0), duration: 0.5),SCNAction.move(by: SCNVector3(x: 0, y: -1.5, z: 0), duration: 0.5)]))
fox.runAction(SCNAction.rotateBy(x: 6.28319, y: 0, z: 0, duration: 1),completionHandler: {
    fox.isHidden = true
    girl.isHidden = false
})
```

###ランダム・ムービング
移動パラメーターをランダムな数値にすることで、バラバラに動きます。
![Apr-12-2021 15-12-42.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/61c36ae9-7642-9426-77fb-0c1c2648a83d.gif)


```swift
for fish in fishes {
   let randomTime = Double.random(in: 3...8)
   let randomPosition = SCNVector3(Float.random(in: -2...2),Float.random(in: -2...2),Float.random(in: -5...0))
   fish.runAction(SCNAction.move(to: randomPosition, duration: randomTime))
}
```

###ふわふわ（Bless）

元のサイズに戻したい時は、scale(by: )ではなくscale(to: )を使うと便利

![Apr-12-2021 17-18-13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/218b3107-42f1-57df-1d3e-a6b6b34b2109.gif)


```swift
omochi.runAction(SCNAction.repeatForever(SCNAction.sequence([SCNAction.scale(to: 1.1, duration: 1),SCNAction.scale(to: 1, duration: 0.5)])))
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)