iOS
SceneKit

iOSのSceneKitで3D迷路ゲームを作ってみたメモ

More than 3 years have passed since last update.


はじめに

iOSにSceneKitという3Dライブラリがあるのですが、学習がてら、それを利用して簡単なゲームを作ってみました。

ThreeDMaze

https://itunes.apple.com/us/app/threedmaze/id973497184

ソースコード

https://github.com/xylitol45/ThreeDMaze

screen640x640.jpeg

気付いたことをメモってみます。


SCNNode.flattenClone

同じ内容のSNNode(3Dオブジェクト)をあちこちに配置する場合、flattenCloneを利用して、コピーしたSCNNodeを配置すると最適化されてよいらしいです。


SCNCameraのxFov、yFovは角度指定

カメラの画角(広角とか)の指定はSCNCameraxFovyFovを利用します。

ただ、何か理由があるのかもしれませんが、他の回転がほぼラジアン指定なのに対し、ここは角度(0-360)で指定するようになってました。


rotateByAngle:aroundAxis:duration:

SCNActionを利用して、SCNNodeに対し、回転や移動などのアニメーションを設定することができます。

回転の指定は色々あるのですが、今回カメラの回転を行う為に、結局 rotateByAngle:aroundAxis:duration:を使いました。


SCNAction.rotateByAngle(CGFloat(M_PI) * -2, aroundAxis: SCNVector3(x: 1, y: 1, z: 1), duration: 10)

他の回転処理を連続で使うとどうもズレてしまう。。。

(四元数とかジンバルロックとかよく分かってないというのもある)

ただし、このAPIを使うと、現在、アプリの申請時に警告が出るようです。


The app references non-public selectors in Payload/ThreeDMaze.app/ThreeDMaze:rotateByAngle:aroundAxis:duration:


でも、ないはずはないので、これはさっくり無視した感じです(リリースはできた)。


カメラの移動とアニメーション

実機での確認はiPhone6がメインでした。

で、当初、迷路内のオブジェクトにもSCNActionでアニメーション効果をつけていたのですが(迷路内のコインをくるくる回してた)、カメラを回転させると、アプリが落ちまくる。。。

動きの早さはそんなに悪くないんですけどね。

結局、アニメーション効果はあきらめました。


SCNSceneRenderer.overlaySKScene

3D画面へのオーバレイ画面として、SCNSceneRenderer.overlaySKSceneを利用し、SpriteKitのSKSceneを設定することができます。

ただ、SpriteKitの感覚で使ってたら若干挙動が違っていて、



  • SKScene.scaleModeがうまく動いてない?frameは実値で指定したほうがよさげ。

  • 親となるSCNViewで再描画されないと、画面更新されないような。結局、CADisplayLinkを利用する形になりました。

        // CADisplayLinkを利用して、loop処理を作る

if displayLink == nil {
displayLink = CADisplayLink(target: self, selector: Selector("loop:"))
displayLink?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
}

func loop(link:CADisplayLink) {

if startTime == nil {
startTime = link.timestamp
}

if link.timestamp - lastTime > 0.01 {
lastTime = link.timestamp
// ここでSKLabelNode変更
refreshTimeLabel(Double(lastTime - startTime!))
self.view!.setNeedsDisplay()
}
}


迷路作成

ここを参考にしたのですが、迷路の作り方は色々あるようです。

迷路自動生成アルゴリズム

http://www5d.biglobe.ne.jp/stssk/maze/make.html

今回は立体ということもあり「穴掘り法(道延ばし法)」というのを利用しました。


  1. まず迷路を全て壁で埋め尽くす。

  2. 適当な基点を設定する。

  3. その基点からランダムに2マス穴を掘れる方向を探す。

  4. 2マス掘って、新たな基点とし、3を繰り返す。

  5. 穴に当たって掘れなくなったら、今までの基点から適当なものを選び新たな基点とする。


3Dモデル

今回は使ってませんが。

SceanKitですが、3Dモデルとして、COLLADAフォーマット(.dae)を扱うことができます。

ただ、これについてはよく指摘されているようですが、プロジェクトに追加すると、独自の形式に変換されているようです。

UIWebView + three.js でこのリソースを扱おうとしても、正しく読み込めません。

.datとか拡張子を変えて追加すると、正しく読み込めるようです。

(でも、おそらくSceneKitからは使えないような)


Unity

世の中的には Unityのほうがメジャーなのですが、SceneKitは無料なので、カジュアルに何か作るにはいいかな、と思います。

Unity無印のiOS出力アドオンっていつの間にか無料になってた。。。