テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】Soft Particleを使って、ポリゴンとパーティクルの交差点がハッキリ見えないようにする

今回はSoft Particleについてです。

Soft Particleはエフェクトの交差点をフェードアウトする

ビルボード(常にカメラを向くビルボード)でパーティクルアニメーションを行うと、ビルボードがポリゴンと交差した際に境目がハッキリ見えてしまう事があります。

そういった時にSoft Particleの機能を使うと、境目をフェードして表現してくれます。

f:id:tsubaki_t1:20170429202157j:plain

対応してるシェーダーとDepthTextureが必要

この機能を有効にするには、Soft Particleに対応しているシェーダー、あとDepthTextureが必要です。

Soft Particleに対応してるシェーダーとは、大雑把に言えばビルトインシェーダーでSOFTPARTICLES_ONが入ってるシェーダーです。

Particleのシェーダーには大抵入っていますが、Mobile/Particleのシェーダーには殆ど入っていません。

f:id:tsubaki_t1:20170429203557j:plain

 

Depth Textureは、Deferredレンダリングならば特に設定しなくても動作しますが、

Forwardレンダリングの場合はCameraコンポーネントのdepthTextureMode で明示的にONに設定する必要があります。

gist.github.com

あとはPlayerSettingsのQuality SettingsでSoft Particleを設定すれば準備完了です。

f:id:tsubaki_t1:20170429204639j:plain

モバイルでも動く

Soft Particleはモバイルでも動作します。

Quality Settingsで設定する際、MobileはSimpleが標準設定で、SimpleはSoft ParticlesがOffになっているので、これをOnにしてやれば動きます。

f:id:tsubaki_t1:20170429205800j:plain

ただしパーティクルはオーバードローが激しくなりやすい項目で、しかもSoft Particleは比較的重いシェーダーとされています。

炎のような単純なスプライトアニメーションなら兎も角、濃い煙を表現する等の、大量かつ広範囲に描画するパーティクルには使わない方が良いかもしれません。もしくは画面解像度を下げるか。

 

Particle AditiveをMobileで選択すると、Mobile/Particleシェーダーをお薦めされます。f:id:tsubaki_t1:20170429210040j:plain

関連

tsubakit1.hateblo.jp

sssslide.com

 
 

【Unity】Ctrl + Dで複製したオブジェクトから(1)を無くし、元オブジェクトの下に生成する

昨日のエディタ拡張で調子に乗って作ってみました。

ただ色々確認してる所、Macでは動かないかもしれません。

Ctrl + Dで複製しかし()は無し

Ctrl + Dでオブジェクトを複製しますが、複製したオブジェクトに(1)等は付きません。また、元となるオブジェクトの真下に生成されます。

f:id:tsubaki_t1:20170428005050g:plain

 

ちなみに、上の並びを本来の機能でやろうとすると、こんな感じ

f:id:tsubaki_t1:20170428005130g:plain

 

 ファイルの複製(適当)

ついでにファイルの場合は複製する機能の残しましたが、適当に作ったのでEdit/Deplicateでやるほうが安全かもしれません。

f:id:tsubaki_t1:20170428004428g:plain

コード

これをEditorフォルダ以下に突っ込めばOKです多分。

gist.github.com

関連

tsubakit1.hateblo.jp

【Unity】Create Emptyは何処に作られるのか?

f:id:tsubaki_t1:20170427232113j:plain

ふと気になったので確認してみました。

空のゲームオブジェクトをを作成する

Unityでコンテンツを作る際によくやるのが、Create Emptyで空のゲームオブジェクトを作成する事です。

作成した空のゲームオブジェクトは、フォルダのように暑かったり、適当なコンポーネントを追加してマネージャーにしたりと、まぁ色々します。

f:id:tsubaki_t1:20170427232323j:plain

ただ、オブジェクト作成時変な座標にある事も多々あります。それを毎回ResetPositionで [0,0,0] にしてる訳ですが、正直面倒と感じる事もあります。*1

f:id:tsubaki_t1:20170427232445g:plain

と、言うことで少し確認しました。

オブジェクトはフォーカスしたオブジェクトと同じ位置に作られる

まず一つ目の要素は、Create Emptyで作成したオブジェクトは、フォーカス(Hierarchyダブルクリックでシーンビューの中心に持っていく)したオブジェクトと同じ位置に生成されるという事です。

参考までに、P1~P3の順にフォーカス→Create Emptyでオブジェクトを生成すると、生成したオブジェクトはP1~P3と同じ位置に生成されている事が分かります。

f:id:tsubaki_t1:20170427233145g:plain

これは「キャラクターの位置フォーカスを置きCreate Emptyすると、キャラクターの位置(Pivotの位置)にオブジェクトが生成される」という動作が期待出来ます。

SceneViewを動かすと、生成位置がズレる

ここでメデタシメデタシで終われば良かったのですが、この多くの人を混乱させる挙動には続きがあります。つまり、SceneViewを動かすとCreate Emptyで生成されるオブジェクトの位置がズレるという事です。

下のアニメでは、フォーカス後に左にシーンビューを動かしています。そうすると、Create Emptyで生成されるオブジェクトの位置がズレます。

f:id:tsubaki_t1:20170427233647g:plain

また質の悪いのがズームの扱いです。

SceneViewのズームはFOVを弄って実現しているらしく、ホィールでズームを行った場合 シーンビューの位置は変わりません

なので、右クリック上下左右でカメラの位置を動かしたケースと違い、ズームだけならフォーカスを当てた位置に生成されます。

f:id:tsubaki_t1:20170427234120g:plain

Create Empty Childは親と同じ座標

なお、Create Empty Childは親と同じPosition・Scale・Rotationを持ちます(なので、相対座標は0となります)

これを便利ととるか微妙と取るかは…いや、微妙ですよね

f:id:tsubaki_t1:20170427234732j:plain

CreateEmptyで変な挙動になるならCraeteEmptyの挙動を上書きすれば良いじゃない!と思ったんですが、残念ながら出来ませんでした。

Cannot add menu item 'GameObject/Create Empty %#n' for method 'CreateEmpty.CreateEmptyObject' because a menu item with the same name already exists.

f:id:tsubaki_t1:20170428000556j:plain

 

と思いましたが、何とかなりました。

MenuItem名を少しズラし、かつGameObject/Create Emptyより高い優先度でMenuItemを用意してやれば、Ctrl + Shift + Nで自分が用意したGameObjectが生成出来ます。あと()とか要らない

gist.github.com

ちょっとした応用・Deplicateから(1)を抜き、親オブジェクトの下に生成する

このギミック使うと、Deplicate(Ctrl + D)も上書き出来ました。()が付かない・現在のオブジェクトの下に生成する複製…みたいな感じで。

f:id:tsubaki_t1:20170428003111g:plain

まぁアセットの複製がCtrl + Dでできなくなる弊害がありますが…ちゃんと拡張すれば何とかなるかな…?

関連

asus4.hatenablog.com

*1:フォルダやマネージャーとして使う場合、座標が0,0,0以外の所にあると色々とややこしい事を起こす事がある

【Unity】Timelineに動的に生成したオブジェクトをバインドする

f:id:tsubaki_t1:20170426221416g:plain

今回はTimelineのデータ情報を流し込む方法についてです。

 

Timelineは使い回せる

Timelineのシーケンスを管理するPlayableAssetsは名前の通りアセットですので、複数のオブジェクトで使いまわす事が可能です。

これを上手く活用すると、特定のイベント…例えば「幅を飛び越える」や「宝箱を開ける」といった部分で、Timelineを活用したアニメーション制御やカメラワーク制御が使用できそうです。

イベントに使う事でAnimatorの構造を簡単にする

 これはTimelineによるモデルに対するアニメーション制御が可能な事を意味しています。なので、例えば「ドアを開ける」「ゲームオーバーになり倒れる」「階段を登る」等の、Animatorで制御すると面倒な(ステートのスパゲティを引き起こしやすい)問題が回避しやすくなります。

ちなみにTimelineのアニメーション流し込みはPlayableAPIを使用しているので、Timelineを使用したくないならPlayableAPIで流し込んでも良いです。

使い回しTimelineを作る時は編集用シーンを用意するが吉

Unity 2017b2で治ってるかもしれませんが、以下のような事があるので、使い回しTimelineを作る時は編集用シーンを作ったほうが良いです。

  1. エディタ操作時のTimelineでシーケンス操作した後に元に戻す機能がスーパー雑
  2. アニメーションはPlayableDirectorではなく親オブジェクトからの相対座標指定で動く

特に2番めの問題があるので、RootMotionが無いキャラクターを移動させるモーションを作る場合は、キャラクターを載せて動かすダミーオブジェクトを用意するのが良さそうです。

Timelineはバインドしたオブジェクトを操作する

Timelineを使いまわす上で重要なのが、オブジェクトのバインドです。

Timelineは基本的にバインドしたオブジェクトを操作します。その為、複数のTimelineが合った場合でも操作する操作する対象を分ける事が出来ます。

例えば上のアニメでは初回のジャンプだけカメラワークの位置が異なります。これは個別にカメラワークの位置を設定出来るために可能な表現です。

f:id:tsubaki_t1:20170426210833j:plain

PlaybleDirectorがオブジェクトへの参照を保持し、Timelineはその情報を使う

Timelineを使う上でのデータのバインドは、多くの場合下のように設定されています。つまり、トラックに露出した項目に設定します。
これをPlayable Directorで見るとBindingsの項目にTimelineで設定したコンポーネントが表示されています。

もしTimelineを複製した際、異なるオブジェクトをバインドしたい場合、PlayableDirectorで参照先を変えてやると、動かす対象が変化します。

f:id:tsubaki_t1:20170426203915j:plain

f:id:tsubaki_t1:20170426204040j:plain

つまりTimelineの参照関係解決の流れは、こんな感じという事です。

  1. Playable Directorにシーン内のオブジェクトへの参照を保持しておく
  2. 実行時、PlayableAssetの情報を元にTrackやAsset、Playable*1を生成
  3. Playable Directorが参照情報をTrackやAssetに参照を流し込む
  4. AssetがPlayableに参照を流し込み、参照情報を使って再生する

 

ちなみにInspectorに表示される項目は設定中にPlayableAssetsの項目ですが、複数のPlayableAssetsの項目が保持出来ます。
これで動的にPlayableAssetsを流し込んだ場合も、バインド機能は動作するという事です。

別シーンのオブジェクトや生成したオブジェクトは動的にバインドする

この参照関係の構築の問題はTimelineが別シーンであったり、動的に生成している場合です。これらは事前に参照関係を設定出来ないので、動的にオブジェクトをバインドする必要があります。

f:id:tsubaki_t1:20170426205659j:plain

PlayableTrackに動的なオブジェクトをバインドする

まずはトラックにバインドします。

PlayableAssetsがバインド可能な項目は、PlayableAssets.outputsから取得出来ます。そこからトラック名が一致するPlayableBindingを取得します。これがPlayableAssetのトラックへの鍵となります。

あとはPlayableDirector.SetGenericBindingで、PlayableDirectorにバインド情報を流し込みます。*2

gist.github.com

なおトラック名とはTimelineのトラック選択時にInspectorに出てくるコレです

f:id:tsubaki_t1:20170426212248j:plain

PlayableAssetに動的なオブジェクトをバインドする

アセットにオブジェクトをバインドします。

こちらは一々個別に設定など出来ないので、Resolverで参照を解決してもらいます。ただExposedReferenceではなく、割とマニュアルな感じです。

 

PlayableAssetのバインドはIExposedPropertyTable経由で保持されている物を使用しています。つまりIExposedPropertyTableにキーとバインドするオブジェクトを与えてやれば良い訳です。
ここでExposedReferenceを使いたい所ですが、ExposedReferenceが設定するキーの値がちょっと分からないので、キーは手前側で勝手に決めてしまった物を使います。

  1. playableDirector.SetReferenceValueでオブジェクトをバインドする。
  2. graph.resolver.GetReferenceValueでバインドしたオブジェクトを取り出す。

gist.github.com

なんでC#のDictionalyでやらないのかという意見があるかもしれませんが、私もそう思います。まぁTimelineの中身がほぼC++っぽいので、こういう形なんでしょうが…

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

*1:PlayableTrackやPlayableAsset

*2:Inspectorは変化しません。