2016年3月31日木曜日

SceneKit - 楽しいけど難しいパーティクル

SceneKitシリーズ 第三弾。今回はパーティクル編です。




Standlandでは、深々と雪が降っている雪国や、キラキラ光るGemmyなどで使ってます。
この効果はパーティクルといいます。

UIKitでもCAEmitterLayerを使用すれば同様な事ができるので、使った事がある人もいるのでは?

UIKit Particle Systems in iOS 5 Tutorial | Ray Wenderlich
UIKit上でパーティクルエフェクトを表示する - Over&Out その後
Swiftでパーティクルの描画☆*:.。.([CAEmitterLayer / CAEmitterCell] 

SceneKitのParticleと、CAEmitterLayer。設定する内容もほぼ同じで、

  • パーティクルの画像
  • Birth rate
  • Life span
  • Velocity
などを設定していきます。

パーティクルの難しさは、組み込む方法よりも、パラメータを調整して "いい感じ" にすることだと思います。
なんというか....やっぱりここにもセンスがいるし、チマチマとした調整を始めると結構時間がかかる。

CAEmitterLayerで、さらに難しくしている要因としては専用エディタがないことなのですが、SceneKit/SpriteKit ではエディタがあるんですよ!


XCodeのファイルの作成でSceneKit Particle Systemを選ぶとテンプレートがいくつか選べます。
作成したファイルを開くと、エディタの表示になります。


PreviewをみつつAttributes Inspectorでパラメータをいじることができます。
SpriteKit(2D)でも同じように作成できますが、SceneKit(3D)のほうが当然ながら設定パラメータが多いです。

エディタがあるということは....つまり.....
こういう作成が得意な人に調整をお願いすることができる
というメリットが! 

このパーティクルのファイルを、CAEmitterLayerにも使えないかと探ってみたのですが方法が見つからず.....残念。

「得意な人はいないけど、凝ったパーティクルを作りたいのだ」
という人は、ツールでカバーする方向も。

購入して試していないので、どこまで連携できるかはわからないのですが...
連携が出来なかったとしても、Particle Designer のように、いろいろサンプルがあると助かると思う。
何事も真似から学びますしw


パーティクルって "こんな感じ" と言葉に表して伝えるのは難しい。
「キラキラしたい」とか「ゴーッと燃える」とか?
そもそもの話として、どんなものがよさそうか? を、自分でイメージが明確になってなかったりもしますよね。
人にお任せで頼むとしても、「こんな感じに近いもの」というイメージを自分で探して、できるだけ伝えるべきと思う!

たとえばー「派手目のおめでとう感」といってもいろんな表現があります。

AngryBird2のスコア表示画面をみてみると....


紙吹雪、星が大きくなった時に弾き出される小さな光、背景でぐるぐる回っているSumbeamや星、明るいところの増減などなどいろいろ効果組み合わさっているのがわかります。
手馴れている感がありますよね....さすが!

紙吹雪のパーティクルを作成するという一つをとっても、
上からパラパラ降ってくるのか
下から吹き上げられるものなのか
AngryBirdみたいにパーン!と弾きだされるものなのか
などによってパラメータが全然違ってきます。

正直、Standlandはキラと光るシンプルなパーティクルだけで逃げてしまった感があります。
いろんなパターンを試してみたのですが、いい感じのものがなかなかできず... 結局、ばっさり捨てて無難なものに。

雪が降っている ようなリニアなパーティクルは簡単ですが、パーン!とはじき出されるような動きがあるものについては、パーティクルだけだとナカナカ難しい。
AngryBirdのようにパーティクル以外の効果を組み合わせて....パーティクルは補助的な役割で....考えたほうがよさそうというのがいまのところの感想です。

センスがいいものを作るのには、アニメーション同様ハードル高めではありますが、うまく使えるようになって、他のアプリにも効果的に使ってみたい。


さて、次は.... Gemmyを歩かせる(衝突判定) の話でもー。





作成したアプリはこちら↓


Standland - 座りすぎ解消!スタンドランド


• • •

2016年3月25日金曜日

SceneKit - カメラはテレビ番組のように

SceneKitシリーズ第二弾。
今回はカメラについて書いてみます。

SceneKitで作成した画面は、カメラを通して表示されます。
カメラの存在は必須で、カメラを作成していなかったらデフォルトのカメラが用意されます。


この図の内容は理解できるのですが、ここから先は専門用語がいろいろ出てきて、3D初心者の私としては最初の難関でした。

今、思うに....
SceneKitの画面ってテレビ番組のようだな と思います。
プログラムを書くあなたは、さしずめ制作プロデューサー。

「カメラさん、主人公を追って!」
「カメラさん、主人公の顔に、ズーム!」
「はい、ここで、1カメから2カメに切り替え!」

(テレビ番組の制作をしたこと無いのでこれまた想像ですが)

iPhoneはテレビ。ユーザは視聴者。
そんな現実のイメージを持ちながら見ていくとわかりやすいのかなと思います。

カメラの機能



SceneKitのカメラを通して見える世界は、カメラの位置だけでなく、角度、FOVなどの属性によって決まります。
いろいろ用語がでてきますが、できることは現実のカメラととても近い。
何かを撮すためには、カメラを持って移動して、角度を調整しますよね。
Storyboard上では、位置はPosition、角度はEulerで設定します。

ズームは、xFOV, yFOVの値で設定。
FOVとはField of Viewの略。日本語でいうと視野とかってところかな。
現実のカメラでいうとレンズとしての機能で、角度を小さくするとズームします。

NearとFarは、描画する範囲。
広大な大地に降り立った時、すっごい遠くは見えなくてもいいはず。
ゲームをやっていても、近くにきたら突然みえるようになるポリゴン、あったりしますよね。
全てを描画するとなると処理に負担がかかるので範囲の制限をかけれるわけです。
現実のカメラでいうとフォーカス? ぼやけるわけでなく、見えなくなるという差はあるけど。

「はい、ここで、1カメから2カメに切り替え!」

カメラは複数台作成ができます。
でも、画面上に表示されるものを撮しているのは1台のカメラ。
そのカメラを指定するのが、SCNViewのpointOfViewです。
画面に表示されているものは カメラ → PointOfView (POV) を経て見えています。


「カメラさん、主人公を追って!」



Standlandのオープニングではこんな感じで動きます。
これを実装するには??

はじめはカメラを動かそうとしました。
このカメラワークをカメラをもって実際やってみるイメージをしてみると....キャラクタを常に中心に表示するためには角度を変えないといけないことが分かりますか?
カメラさんは、上空でカメラを下に向けている状態からはじまり、地上に降りてくるとともにカメラを水平方向に角度を変えています。
カメラの角度は計算すれば求められるものではあるのですが、実装していくのはまぁ面倒。

そこで使えるのが、SCNLookAtConstraint という制約です。

これでカメラの位置を移動したら常に指定位置がカメラ向きになるように自動的に角度を調整してくれるようになります。とても便利!
イメージ的には、カメラとターゲット位置が紐で結ばれている...とか、ヘッドセットのカメラとかそんな感じでしょうか。
この制約は、スポットライトにも使えます。

これである程度カメラがうまく動くようになったものの、問題点が発生。
カメラ制約:Z軸と、カメラ位置:Z軸の値が違うと、カメラ位置の:Y軸が正数になるにつれて世界のZ軸が反転してしまうという....。
簡単にいうと、有る特定の位置にカメラを移動すると世界がくるっと反転してしまうという現象。

なので、Standlandではすったもんだした挙句、カメラを動かすのではなく、POVのRotationを変えること(=世界を回転すること)で実装しました。

「カメラさん、主人公の顔に、ズーム!」

実は、カメラへのSCNLookAtConstraintの制約は結果的には使用していて、利用箇所はズームです。

PinchGestureをTriggerに以下のようなコードにしています。
PinchGestureのScaleを元にズーム値を決めて pointOfView.camera.xFov に値を設定してズーム。Gestureが終わった時(指を離した時)、元のFovの値に設定して元のズームサイズに戻しています。

さて、ここで注意すべき箇所は、influenceFactor の存在。



Standlandで実現したかった動きとしては、ズーム前とズーム後で、画面の中心位置を変えること。

ズーム前はキャラクタの少し上が中心にしたかったのですが、その位置のままズームすると、キャラクタが見えなくなってしまいます....。

そこで使っているのが、influenceFactor
factorの値を1.0にすると制約あり、0.0にすると制約なしになります。

SCNLookAtConstraint の制約をPOVに設定し、influenceFactorを0に設定。
制約は、ズーム後の位置にしておきます。

そして、PinchGestureでの処理中に、ズームしていればfactorの値も1.0に近づけるように変更していく(=制約をだんだん有効にしていく)ということをしています。


カメラシリーズ、これでおしまい。
カメラはなかなかハードですよね... 次は気軽にパーティクル編を書いてみます!



作成したアプリはこちら↓


Standland - 座りすぎ解消!スタンドランド

• • •

2016年3月23日水曜日

SceneKit - 世界はSCNViewでできている

先日リリースしたStandlandでは、SceneKitを使ってみました。
SceneKitを使って実際にアプリをリリースした人はまだあんまりいないだろうなーということで、どんな感じだったかを書いてみようと思います。

SceneKitとは、iOS SDKに含まれている3Dグラフィックのフレームワークです。
モノとしてはUnityと同じアプリケーション層。

球体とかにテクスチャを貼って配置してみたり、光源を置いて影をつけてみたり、空(Skybox)を設定してみたり、重力に合わせて動かしてみたり... と最初に試してみる事としてはUnityと多分変わらないはず。

Metalを使うには iOSの新グラフィックAPI - Metal入門してみる のような処理が必要なのですが、これらを簡単に扱えるようにしたフレームワークです。

では、何でSceneKitを選択してみたか? というと、
  • iOSに特化しているから、汎用的に作られているものよりも処理が早いはず
  • ブラックボックスが少なくコードでいろいろ書ける方が、(私としては)とっつきやすい
  • 直接Metalを扱うほどシビアなものを作ろうとしているわけはない
ということ。

裏の気持ちとしては、
  • どんなものか知りたいという単純な興味
  • SceneKitで使える技が他のアプリ開発にも役立つかもしれない(Unityを学ぶよりは)
  • Appleさんにフィーチャーしてもらいたい
というのも、もちろんあります(笑)。

せっかくなのでSceneKitを使う人のためにあしあとを残してみます。
が、全体は大きすぎるので、今回はSceneKit全体像から。

世界はSCNViewでできている

SceneKitを表示するための大元のViewがSCNViewです。
SCNViewの継承元はUIView
つまり通常のアプリのUIViewの中に一部として入れることもできちゃいます。

基本構成はscnファイルで

SCNViewにあるSCNSceneが、シーンを管理しているクラス。
SCNSceneは、scnファイルを指定してインスタンスします。

scnファイルは、表示するデータが入ったバイナリファイル。
COLLADA形式の3DモデルをXCodeで変換して作成します。
COLLADAがなくても、簡単なものであればXCodeのエディタで作成できます。

実際には一つのscnファイルで全てのモデルを配置するのではなく、各部品で分けて、組み合わせていく形になるかと思うのですが、この部品もscnファイルで作成します。

scnファイルの中に他のscnファイルの参照を置くことができるし、scnの中のノードをプログラムからアクセスして他のSCNSceneに追加もできます。

実際、Standland でも
scnファイルを組み合わせて、世界全体を作成しています。



キャラクタの動きなどのアニメーションについても、scnファイルで切り出しします。
これでアニメーションを切り替えることがプログラムから可能になります。

イベントの取得はUIViewと同じ

UIGestureRecognizerを登録するとちゃんと反応します。

TouchEvent
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?)
もちゃんと渡ってきます。

Standlandでは、スワイプ操作でカメラ向きをかえたり、ダブルタップでみんなが一斉にジャンプしていますが、そのイベントの発火元はこれらになっています。

UIViewと同じように扱えるので、すでにアプリ作成を経験している人にとっては良い点ですね。

SceneKit 内のタップ判定



青いちっこいのがGemmy。
この子をタップするとGemゲットできたりジャンプしたりします。
その時必要になるのが、SCNKit上では、なにがタップされたのか?の判定です。

ここで使用するのは、SCNViewの

func hitTest(point: CGPoint, options: [String : AnyObject]?) -> [SCNHitTestResult]

というメソッド。
これでUITapGestureRecognizerで取得できたPointを使用して、SCNKit上でHitしたオブジェクトが取得できます。

HitしたのがGemmyなのか?うさぎなのか?は、ノードの名前で判断します。
そのため、scnファイルの中で設定しているノード名はちゃんとルールを用意しておきましょう。

2DのOverlayはSpriteKit

例えば、ゲーム終了後にスコアを画面上に2Dで表示したい。
という場合、overlayを設定することができます。
overlayは、SKScene .... つまり、SpritKitフレームワークのオブジェクトを利用します。
SCNSceneRenderer#overlaySKScene

...が、Standlandではoverlayは使わず、UIViewをSCNViewの上に置いちゃっています。
理由としては、Storyboard上でレイアウトをしたかったから。
そして、ボタンなどのハイライトとかUIKitの便利な機能を使いたかったから。

AppleTVにも対応する場合、overlayを使いSceneKit/SpriteKitだけで作成した方が楽かもしれません。
あと、SCNViewをインスタンス中にUIViewで表示、アニメーションとかすると、ビシっと線が入ったりして苦しそうになりますのでご注意を。


今日はこれでおしまい。
次回はカメラについて書いてみようと思います!



作成したアプリはこちら↓


Standland - 座りすぎ解消!スタンドランド
• • •

2016年3月5日土曜日

キレイなステータスバーでアプリ用のスクショを撮る方法

アプリを作成し終わった後、面倒なのはスクリーンショットの用意ですよね。
 いろんな端末サイズ × 対応言語 の数が必要で、うんざりします。

Timesheetの場合だと、
スクリーンショット5枚 × 3言語 × iPhone/iPadの6サイズ = 90 枚


90枚!!



 以前、Sketch3のSymbolを使って作っていること を書きましたが、 元となるスクリーンショットを撮る作業だけでもかなり大変。 

スクリーンショットを撮る際に、気をつけたいこととしてはステータスバーです。
普通に撮ると、



...とSoftbankというキャリアだったり、バッテリー容量が100%ではなかったりすることも。
後で画像を細工するという手もありますが、そんな手間は掛けたくない。
考えただけでも気が遠くなって気持ち悪い。


で、キレイなステータスバーにしてスクリーンショットを撮る方法をご紹介。


実機で撮る場合

1. iPhoneをMacとをUSBでつなげる
2. QuickTimePlayerのアプリを立ち上げる
3. メニューから File > New Screen Recording を選択
4. 接続先を iPhoneにする



上図で aqubi 6s とあるのが私のiPhone。

これだけで...(記録を実行せずとも)、iPhone上のステータスバーが以下のようになります。



キャリアは消え、時間は 9:41 AM。バッテリーも100%に。

USBつないでいるので、バッテリー表記が充電中の緑になっちゃうんですがこれを無しにする方法がわからない。あるのだろうか??


シミュレータで撮る場合


SimulatorStatusMagic という素敵なものがGithubにあります。
CocoaPodsで取り込むという形もできるようですが、私はサンプルプロジェクトを実行して、Apply Clean Status Bar Overrides のボタンをポチります。

そうすると、それ以降、そのシミュレータはクリーンなステータスバーになります。
(サンプルプロジェクトを終了してもその効果が残る)

戻したいときは、Restore Default Status Bar をポチり。


付録: 端末の言語を簡単に切り替える

XCodeのプロジェクトの、Shemeに言語設定があります。


XCodeからiPhone実機で実行した際にも、Schemeの言語が反映されます。
iPhoneの設定で言語切替をすると結構時間がかかるので、便利です。

付録:  タップしたところにマークを入れる

動画を作成する際、タップしたところにマークがあるとわかりやすくなります。
これを実現するものとして COSTouchVisualizer というのがありました。

いま試してみたのですが、なかなかよさ気デス。


• • •