0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SceneKitでサイコロが転がるようなアニメーションを再現する

Last updated at Posted at 2020-10-11

##はじめに
サイコロが転がるようなアニメーションを再現します。Unityでは軸を設定してその周りの回転を行うことができるRotateAroundというメソッドが用意されていますが、SceneKittには無いようです。主な動きは↓こんな感じ。SceneKit SceneFileの使い方についても触れています。

##考え方のヒント・実装の流れ

  • Rotateなどのメソッドはオブジェクトの座標を原点とし、回転する方向を決めて、回転を行っている
  • 親と子の階層関係にあるオブジェクトは、親が動くと子も動く
  • 球や立方体のような形を持たないオブジェクト(ここではemptyNodeとしている)を生成することも可能

##再現したい動きをSceneKit SceneFileで確認する
SceneFileでは、Unityのように3Dオブジェクトを実際に配置することが可能です。動きの確認だけでなく、ファイルをそのまま起動させることもできます。
スクリーンショット 2020-08-31 16.05.54.jpg スクリーンショット 2020-08-31 16.06.11.jpg

スクリーンショット 2020-08-31 16.10.14.jpg

では実際に回転の流れを見ていきます。
###1.boxを追加する
右上の➕からboxを選択し、ドラッグ&ドロップします。その後、position(座標)を(0,0.5,0)、size(大きさ)を(1,1,1),Eular(回転)を(0,0,0)に設定します。
スクリーンショット 2020-08-31 16.14.23.jpg
###2.形を持たないnodeを追加する
右下の➕ボタンを押し、nodeを追加します。<untitled> が追加されればOKです。(以下これをemptyNodeとします。)
右側に回転する動きを再現したいので、中心となる立方体の辺の中点にemptyNode(0.5,0,0.5)に移動します。
スクリーンショット 2020-08-31 16.15.06.jpg

###3.emptyNodeの階層下にboxを配置する
階層関係にあるnodeにおいて、子nodeは親nodeの動きの影響を受けます。boxをemptyNodeの下にドラッグ&ドロップし、子nodeとして設定します。
スクリーンショット 2020-08-31 16.15.44.jpg
###4.emptyNodeを回転させる
emotyNodeのz軸を-90度回転させることで、回転を表現することができます。
スクリーンショット 2020-08-31 16.16.04.jpg スクリーンショット 2020-08-31 16.16.22.jpg

##SceneFileで確認した動きをコードで再現する
SCNSceneクラスを継承したGameSceneクラスを作成します。GameSceneにはboxNodeとemptyNodeをプロパティとして持たせています。また、boxNodeの座標である0,0,0.5をそれぞれx,y,zをとして定義します。

class ViewController: UIViewController {
    var x = 0.0
    var y = 0.5
    var z = 0.0
@IBOutlet weak var test: SCNView!
    let scene = GameScene()
    override func viewDidLoad() {
        super.viewDidLoad()
        test.scene = scene
    }
}

rightボタンを紐付け、動きを記述します。

@IBAction func right(_ sender: Any) {
        //EmptyNodeを定義
        scene.emptyNode.position = SCNVector3(x: Float(scene.boxNode.worldPosition.x+0.5), y: Float(scene.boxNode.worldPosition.y-0.5), z: Float(scene.boxNode.worldPosition.z))
        scene.emptyNode.addChildNode(scene.boxNode)
        scene.boxNode.worldPosition = SCNVector3(x,y,z)

        let a = SCNAction.rotate(by: -CGFloat(Float.pi/2), around: SCNVector3(0,0,1), duration: 0.1)
        scene.emptyNode.runAction(a)
        x+=1
    }

基本的にはSceneFileで確認した動きをそのまま書くだけなのですが、addChildを行うと動くことが確認されたので、最初に定義したx,y,zを用いて解決しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?