Apple Engine

Apple, iPhone, iOS, その周辺のことについて

SceneKit のテクスチャに SpriteKit の SKScene を貼り付けて複雑な動きをするマテリアルをつくる

f:id:x67x6fx74x6f:20190307153212g:plain  

以前の記事で SpriteKit の SKVideoNode を使用して SceneKit のテクスチャに動画をループ再生する記事を書いた。

SpriteKit のシーンを貼り付けているため、基本的には SpriteKit で使用している機能を使いアニメーションや インタラクションをテクスチャとして使用することができる。

本来は Metal シェーダーでつくるべきだが、SpriteKit は SceneKit と同じような方法でコンテンツをつくることができるため学習コストが少なくインパクトのあるマテリアルを表示することができる Unity など他のゲームエンジンにない珍しい機能である。

SceneKit でマテリアルを表示する前に SpriteKit で画像つくってから表示するため、ある程度処理で負荷がかかる。
SceneKit の showsStatistics = true で表示される統計情報の 2D や Rendering で負荷が上がるのでここら辺を見ながら調整することになるだろう。

 

試してみる

f:id:x67x6fx74x6f:20190307152721g:plain

見た目でわかりやすく、他のゲームエンジンで面倒なのはマテリアル内で表示されるパーティクル。

SceneKit + SpriteKit の場合、particle.sks (SpriteKit のシーンファイル) のパーティクルを設定して SpriteKit のシーンに設定、再生して、それを SceneKit のテクスチャとして貼るだけだ。

f:id:x67x6fx74x6f:20190307152518p:plain
Xcode で SKEmitterNode のパーティクルを編集

 

気をつけてほしいのは SpriteKit のシーンである SKScene は SKView を設定することでフレームが動き時間を刻み始める。
そのため、SKAction や動画の再生などシーン内でフレームに関与するもの以外では SKScene は再生されない。
パーティクルなどフレームに依存するものは置いただけでは再生さないので、isPaused を false にする必要がある。

skScene = SKScene(fileNamed: "texture.sks")
skScene.isPaused = false

 

今回は、シーンの sks でパーティクルを設定して、シーン全体をテクスチャにしているが、 コード上で空のシーンを設定して、SKEmitterNode でパーティクルの sks 読み込んだりしても良いだろう。

シーン全体を sks でつくると特にインタラクションがないと場合は sks ファイルだけで振る舞いを確認ができるので便利。

 

SceneKit で SKScene をテクスチャで設定する際の注意点

SceneKit では もう1つ SKScene を設定することができ、 overlaySKScene で画面最前面に SKScene を設定し HUD のように UI としてするものがある。

overlaySKScene は SKScene を貼り付けた場合そのまま表示されるが、
SKScene をテクスチャとして使用する場合は Y 軸が反転されてしまうため、
文字など上下(天地)で見た目が異なるものがを表示する際はそれをなおす必要がある。

 

修正方法はいくつかあるためまとめてみた。

  • SKScene の Y スケールを -1 にする
  • SKScene に SKCameraNode を置きカメラを反転、Y スケールを -1 にする
  • マテリアルの contentsTransform でテクスチャを配置する座標を行列から変更する
  • ジオメトリを反転させる(板ポリなど平面に貼る場合など)
  • ジオメトリの UV の設定(Texture Coordinate)を事前に反転させる

 

SKCameraNode で反転すると SKScene 内で完結するため、sks ファイルで SKScene を設定している場合、イニシャライズ後反転処理をしなくてもよくなる。

ものによっては SceneKit からのインタラクションでジオメトリのタップした場所を SKScene に渡す際に面倒になるかもしれない。

 

サンプルファイル

github.com

 

まとめ

シェーダーを書く場合と比べ、SKSpriteNode などのノードを SKScene に addChild させて、状況によっては SKAction を入れてアニメーションをさせたり、インタラクションを入れたり、簡易的かつ高度なことができることがわかる。

一応、それなりの負荷がかかるのでご利用は計画的にといったところ。