2014年12月1日月曜日

パーティクルをいじる ~ Candy Rock Star

公開されているUnityちゃんの「Candy Rock Star」でパーティクルをいじってみたメモ。


(Unity上で既に「Candy Rock Star」が動いてる前提。理解不足などある可能性大なので注意)。



■手動でいじってみる


#1.パーティクルを放出しているオブジェクト

Unity上で再生してHierarchyウィンドウを見てみると Confetti(Clone) というオブジェクトができている。
これがパーティクル放出を担当しているオブジェクト。
(動的生成されているので再生中しかHierarchyウィンドウに現れない)




#2.パーティクルの色を手動で変更

再生を一時停止して、Hierarchyウィンドウ > Confetti(Clone) 配下の オブジェクトParticle System を選択する。
Inspectorウィンドウを見るとパーティクル設定が見える。
色は Start Color をいじれば即再生に反映される。
 


#3.パーティクルを手動でON/OFF


Inspectorウィンドウ上部のオブジェクトParticle Systemを有効/無効のチェックを操作するとパーティクル放出もON/OFF変化する。

 

#4.パーティクルのレイヤ

パーティクル用に設けられたレイヤ名 Particle に Confetti(Clone) は配置されている。
このオブジェクトの子には Directional Light があり、それも同じレイヤにある。
ということは Directional Light を調整すると Particleだけを対象としたライト効果を操作できる。
 

#5.動的生成元


ここまでみてきた Confetti(Clone) の動的生成元(プレハブ)はProjectウィンンドウ内の /Asset/UnityChanStage/Prefabs/Confetti。
(※Confetti (light) というのも見えるがParticle Systemを1つにした軽量バージョンかもしれない?)
変更を加えたい場合はこちらのプレハブを変更すれば再生時に反映される。



■再生時のパーティクル起動


/Asset/UnityChanStage/Prefabs/Confetti の中のスクリプト PropActivator が再生後パーティクルの放出をしている。

これは前述でInspectorから手動でON/OFFした操作をスクリプトから行っているだけ(gameObject.SetActive(true); )。

ただ、動的生成されている点に加え、呼び出しシーケンスが少々複雑であった。

  1. 再生開始
  2. オブジェクト/Stage Director内のスクリプト StageDirector が実行開始。
    StageDirector の Inspector の Prefabs Needs Activation は動的生成するオブジェクトの一覧の配列。ここに Confetti が事前に登録されている。
    スクリプト StageDirector はこの一覧のオブジェクトを(Awake()内から)動的生成する(インスタンス化)。
     
  3. スクリプトPropActivator内 void ActivateProps() の呼び出し元は?
    動的生成された オブジェクトConfetti(Clone) にはスクリプト PropActivator が入っているが、Start()もAwake()も無い。
    void ActivateProps() のみがあるだけでpublic関数でもない。なので外部からの通常の関数呼び出しは不可能。
    しかしこの関数は再生開始後しっかり呼びだされる。
    つまり「別の方法」で呼び出されている。
     
  4. ブロードキャスト経由で呼び出し。
    スクリプト PropActivator の void ActivateProps() を呼び出している箇所はどうやらスクリプト StageDirector 内の void ActivateProps()。
    ここからブロードキャストメッセージ経由で呼び出している様子。
    メッセージの送り先オブジェクトは配列 prefabsNeedsActivation(オブジェクト/Stage DirectorのInspectorで見える)を対象に送り付けている。
     
  5. 管理の大元スクリプト StageDirector 内の public void ActivateProps() を呼び出すコードが存在しない。
    ここまでで、オブジェクト/Stage Director 内のスクリプト StageDirector の public void ActivateProps() がパーティクルオブジェクト郡へメッセージ経由でオブジェクトの有効化=パーティクル放出開始をしていると見て取れる。
    しかし当のこの関数 public void ActivateProps() をアクセスしている箇所がC#のコード上に存在しない。
    どこから呼ばれているのか?
     
  6. Animation Eventから呼び出されている。
    Hierarchyウィンドウでオブジェクト/Stage Director を選択。
    上部ツールバーのWindows > Animation(又はCTRL-6)。
    これでオブジェクト/Stage Directorに紐ついている(?) Animationの状態が確認できる。
    (まさにBlenderのNLAエディタみたいな感じ?)
    ホイールをまわすと時間スケールを変えて見れる。
    ここから関数ActivateProps()が呼び出される。
     

 ■Animation Event

 上部ツールバーのWindows > Animation(又はCTRL-6)で開くと以下のように見える。


このタイムライン上にイベントを打ち込めるようで、そのイベントから関数呼び出しができるようだ(白い縦棒がイベント)。
白棒にマウスオーバーするとイベントでの呼び出し関数名が見える。

この白棒のある横軸のタイムラインエリアで右クリックAdd Animation Eventでイベント追加&呼び出し関数の指定ができる。
この際当該オブジェクト内スクリプト(複数あれば全部)のpublic関数が候補にでてくる様子。




■まとめ?

たかがパーティクルのON/OFFなので、対象オブジェクトのGameobjectを取得&操作で済みそうだと思ったら、結構複雑なことをしていた。

○BroadcastMessageによる制御

まずBroadcastMessageを使う意味について。
思うに対象オブジェクトとその階層下ならどこに移動しても制御可能なのがメリット・・・だと思われる(相手がpublic関数でなくても呼べる)。
複数Objectに増えてもそのまま対応できる。

結果的に Candy Rock Star では対象オブジェクトそのものにスクリプトが付いているが、開発中にスクリプトを子に移動したりしても呼び出してくれるので、これはちょっと楽かもしれない。

これを Getcomponents() でスクリプトのハンドルを拾う場合は子階層も追跡して拾うことになる
(自前追加実装部分ではこれをやっているが、ちょっと動きを確認したい時はメッセージの方が楽だとは思う。ただメッセージは重いので多用注意ぽい)。

今回の当該箇所はパーティクルの関数呼び出し回数も少ないので、開発中の簡便さでこうなっているのかなと推察。子オブジェクトの1パーティクル/2パーティクル版にもそのまま対応できるし。



○Animation Event

これは・・・めっちゃ便利そうです。
そしてこれに気づく前に、経過時間で各種自前イベント発生&処理を振り分ける機構を既にC#で実装、イベントもほとんど実装し終わってしまったのは内緒・・・(号泣;

パーティクルを先に手をつけとくべきだったか・・・Orz

いやほんとこの機能は便利だと思います。特に Candy Rock Star のような時間進行でイベントが発生するものは。



やはり人のコードを読むのは勉強になりますね。
Candy Rock Star は良い題材だと思います。




0 件のコメント:

コメントを投稿