工場裏のアーカイブス

素人によるiPhoneアプリ開発の学習記

SceneKitにおけるパーティクルシステムの利用

SceneKitにはパーティクルシステムが用意されており、炎、煙、爆発、雨などのエフェクトを手軽に美しく表現することが可能です。本記事ではその利用法の例について簡単にメモします。
 

パーティクルファイルを利用する方法

ファイルをプロジェクトへ追加する
  • Xcode(本記事執筆時点:Version 6.1.1)には、下図のようにリソースとして「SceneKit Particle System」というファイルが用意されています。これを利用すると、比較的簡単にパーティクルシステムを利用することが可能になります。まずは新規ファイルとして、これをSceneKitのプロジェクトに追加して行きます。

f:id:fleron:20150210000250p:plain

  • まず下図のダイアログが表示されます。SceneKitではパーティクルシステムの様々なテンプレートが用意されており、ここではそれらを選択することが出来ます。本記事では「Fire」を選択します。なお、テンプレートの一覧については本記事の末尾にまとめてあります。

f:id:fleron:20150210001013p:plain

  • 続いて、ファイル名を入力するダイアログが表示されますので、分かりやすい名前を付けます(本記事ではデフォルトの「MyParticleSystem」という名前のままにします)。これでプロジェクトに「〜.scnp」というパーティクルファイル、およびパーティクル表示用の画像ファイル(テンプレートにより異なる。Fireの場合は「Spark.png」)が追加されます。

  • パーティクルファイルをプロジェクト上で選択すると、下図のようなエディタが起動します。右側のパネルで様々なプロパティを設定し、その効果を視覚的に確認しながら、パーティクルシステムにより望みのエフェクトが得られるよう調節することが出来ます(本記事ではデフォルトのままにします)。

f:id:fleron:20150210222342p:plain

実際にパーティクルを表示させる

先程のリソースファイルを用いて、実際にパーティクルを表示させる簡単なサンプルコードを以下に示します。

//GameViewController.swiftの中身を書き換え
import UIKit
import QuartzCore
import SceneKit

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let scene = SCNScene()
        
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 20)
        
        let pyramid = SCNPyramid(width: 2.0, height: 2.0, length: 2.0)
        pyramid.firstMaterial!.diffuse.contents = UIColor(red: 0.8, green: 0.2, blue: 0.2, alpha: 1.0)
        let pyramidNode = SCNNode()
        pyramidNode.geometry = pyramid
        pyramidNode.position = SCNVector3(x: 0.0, y: 0, z: 0)
        scene.rootNode.addChildNode(pyramidNode)
        pyramidNode.runAction(SCNAction.repeatActionForever(
            SCNAction.rotateByX(0.1, y: 0.2, z: 0.0, duration: 2.0)
        ))
        
        //パーティクルシステムのオブジェクト生成、およびノードへの追加
        let fire = SCNParticleSystem(named: "MyParticleSystem.scnp", inDirectory: "")
        pyramidNode.addParticleSystem(fire)

        let scnView = self.view as SCNView
        scnView.scene = scene
        scnView.allowsCameraControl = true
        scnView.autoenablesDefaultLighting = true
        scnView.backgroundColor = UIColor(red: 0.6, green: 0.6, blue: 0.8, alpha: 1.0)
    }
    
    override func shouldAutorotate() -> Bool {
        return true
    }
    
    override func prefersStatusBarHidden() -> Bool {
        return true
    }
    
    override func supportedInterfaceOrientations() -> Int {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
        } else {
            return Int(UIInterfaceOrientationMask.All.rawValue)
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}


ポイントとなるのはこの部分です。

let fire = SCNParticleSystem(named: "MyParticleSystem.scnp", inDirectory: "")
pyramidNode.addParticleSystem(fire)

パーティクルを表示させるには、まずはSCNParticleSystemメソッドでファイルを読み込み、パーティクルシステムのオブジェクトを生成します。なお、このメソッドには「inDirectory」という引数がありますが、プロジェクトに追加したファイルを利用する場合は空欄(””)で問題ないようです。

そしてオブジェクトを、立体モデルなどのノードにaddParticleSystemメソッドで取り付けることにより、そのノードからパーティクルが放出されるようになります。SceneKitではこのような形でパーティクルシステムを利用します。

サンプルコードを実行すると、ピラミッド型の立体モデルから「Fire」テンプレートのパーティクルが放出され、あたかもピラミッドが炎上するようなシーンが表示されます。
f:id:fleron:20150210224702p:plain
 

コード上で設定を行う方法

パーティクルファイルを用いず、以下のようにコード上でオブジェクト生成、およびプロパティ設定を全て行うことも可能です。

let parSys = SCNParticleSystem()

parSys.birthRate = 100
parSys.particleColor = UIColor.yellowColor()
parSys.emissionDuration = 0.1
parSys.particleSize = 0.05
//…………以下省略


もちろんパーティクルファイルを用いる場合でも、同様にオブジェクトのプロパティ設定をコード上で変更することが出来ます。例えばパーティクルの放出をオフにしたい場合は、「birthRate」プロパティの値を0に変更するという方法が使えます。
 

パーティクルシステムのテンプレート一覧

最後にパーティクルシステムのテンプレート(XcodeのVersion 6.1.1時点)の概要についてまとめます。

  • Bokeh
    • 黄色い光の粒が、湧き上がって消えていくようなエフェクトです。
    • パーティクル表示用の画像ファイル:bokeh.png

f:id:fleron:20150211000423p:plain

  • Confetti
    • 紙吹雪が舞い落ちるエフェクトです。なぜかパーティクルエディタ上ではグラフィックが表示されないようです(バグ?情報不足により不明)。ただし実際のプロジェクト上で用いると、下図のようにきちんと表示されます。
    • パーティクル表示用の画像ファイル:confetti.png

f:id:fleron:20150211001118p:plain

  • Fire
    • 炎が燃え上がるエフェクトです。
    • パーティクル表示用の画像ファイル:spark.png(Rain、Reactorテンプレートと共通)

f:id:fleron:20150211002233p:plain

  • Leafs
    • このテンプレートは選択しても、何のファイルも生成されないようです (バグ?情報不足により不明)


  • Rain
    • 雨が降り落ちるエフェクトです。
    • パーティクル表示用の画像ファイル:spark.png(Fire、Reactorテンプレートと共通)

f:id:fleron:20150211002807p:plain

  • Reactor
    • 激しい閃光のようなエフェクトです。
    • パーティクル表示用の画像ファイル:spark.png(Fire、Rainテンプレートと共通)

f:id:fleron:20150211002910p:plain

  • Smoke
    • 煙が立ち昇るエフェクトです。
    • パーティクル表示用の画像ファイル:smoke.png

f:id:fleron:20150211003009p:plain

  • Stars
    • 画面奥から手前に向かって、光の粒(星?)が飛んでくるようなエフェクトです。
    • パーティクル表示用の画像ファイル:star.png

f:id:fleron:20150211003058p:plain