【Unity】複数のColliderを結合するComposite Collider 2Dを使って少し遊ぶ
今回はUnity 5.6に追加されたComposite Collider 2Dについてです。
Compound Collidersという機能
Rigidbodyの下にColliderが複数ある時、実はUnityはColliderを一つにまとめて処理してくれます。これで動かす場合、MeshColliderよりも高速で動作します。

こういったCompound(複合)コライダーはMeshColliderやPolygonColliderより大体高速で動作し、かつMeshCollider系の制約も殆ど受けないので色々と便利です。
例えば、下にMeshColliderとComposite Colliderで作成したモデルを用意してみます。
当たり判定は大体同じように作れますが、MeshColliderはCompositeColliderと比較して、単純に当たり判定の計算負荷が高く、アニメーションに非対応で*1、かつMeshCollider同士の当たり判定が出来ない問題があります。
そのため、単純な形状のコライダーを動かして当たり判定を作るCompoundColliderという機能があります。

ちなみに、CompoundColliderはAColliderBuilderでサクっと作れます。
https://www.assetstore.unity3d.com/jp/#!/content/15058
CompositeCollider2Dという機能
さて、5.6でCompoundColliderに微妙に似てますが異なる機能が追加されました。CompositeColliderなるコンポーネントです。
これは複数のCollider2D(MeshColliderとBoxColliderのような頂点ベースのコライダー)を結合し、一つのコライダーに変換する機能みたいです。
例えば下のように、複数のBoxColliderが同じ範囲に入ると、一つのColliderのように結合されているのが分かります。

Colliderの結合は、同期(動かした時に計算?)、非同期、スクリプトからのアクセスの3タイプがあります。要するに、このメッシュ結合はランタイムで動きます。

ちなみに結合コストは結構高いのか、弾幕を作り「一つのRigidbody + 一つのComposite Collider(内部に500個程のCollider)」をやってみた所、バラバラに動かしたほうが早かったです。
また、Geometry typeをOutlineに設定すると、コライダーの形状に沿ってコライダーを作成するみたいです。

ダイナミック洞窟生成
この機能で思いついたのが、ダイナミック洞窟生成です。
やってる事は物凄い単純で、Geometry TypeをOutlineに設定し、あとはモノをどんどん増やしていくだけです。
下のようになります。
Unity 5.6のCompositeCollider2Dでダイナミック洞窟生成 pic.twitter.com/jN2vAuA98V
— 椿 (@tsubaki_t1) 2017年2月21日
Unity 5.6のCompositeCollider2Dのダイナミック洞窟その2。生成する穴を斜めにしたり、唐突に下に穴を空けてみたり pic.twitter.com/8DT3AjI6VJ
— 椿 (@tsubaki_t1) 2017年2月21日
作り方
- 結合するCollider2Dの付いたGameObjectを用意する
- CompositeCollider2Dの付いたGameObjectを用意する
- 1を2の子オブジェクトとして配置
- 1のColliderのUse By Compositeにチェックを入れる

後はEdge Radiusの値を調整します。小さすぎると当たり判定が貫通する事がありますし、大きすぎると凄い浮きます。

後はComposite ColliderにはRigidbodyが付いてくるので、BodyTypeをStaticもしくはkinematicに設定しておきます。

なんか、コレだけで何かゲームを作れそうな気がしなくもないですね。穴掘りゲーム的な。
関連
*1:メッシュを作成しMeshBake等でメッシュ情報を更新しなければ当たり判定が付いてこない
【Unity】Area Lightと、Emissiveな材質を持つ発光するオブジェクトが輝けと囁く
Unityのライティングシステムの隅にひっそりと存在するArea Light(エリアライト)、その知られざる生態系について、今回は踏み込んでみようと思います。
影の表現が柔らかくなるAreaLight
AreaLightですが、マニュアルを見ても「ライトが柔らかくなる」的な事しか書いていません。
エリアライトは複数の異なる方向から同時にオブジェクトを照らすので、他の種類のライトと比べてシェーディングが柔らかく繊細になります。
細かい事は置いておいて、実際にAreaLightとDirectional Lightを比較すると、確かに影がかなり柔らかくなっています。左がAreaLight、右がDirectional Lightです。
Directional Lightはハッキリ輪郭が見えるのに対し、AreaLightは濃淡はハッキリしていますが輪郭はボヤけて見えます。

広い範囲からの照射ばぼんやり、狭い範囲からの照射はハッキリ
Area Lightの挙動は2パターンのライト画像を比較すると、何となく想像が出来ます。
下にAreaLightの横幅が狭い物と広い物を用意して比較しました。狭いAreaLightは影の濃淡がハッキリと見えていますが、広いAreaLightは全体的に薄く広く広がっています。


実際の実装は分かりませんが、挙動としては多分こんな感じです。
AreaLightは複数の異なる方向から対象のオブジェクトを照らして、ふんわりと柔らかい影を表現してるんじゃないかなと思います。

ちなみに現実も、空も光は太陽から直で来る訳ではなく大気である程度拡散してから降り注ぐ感じになると思います。それは正しいか?もっと詳しく?そんなこと俺が知るか!
AreaLightの影は静的なオブジェクトに焼く
ふわっと優しくなるAeraLightは、残念ながらリアルタイムに影を表現する事が出来ません。基本的に静的なオブジェクトに焼き、ライトマップを使用する感じで利用します。
基本的な光表現はLightProbeでダイナミックなオブジェクトに受け渡します。また、ScreenSpaceAmbientOcclusion等でAO表現や古き良き丸影を使うと、意外と馴染んで見えたりします。

発光するEmissiveオブジェクト
AreaLightと似たような性質を持つ機能として、Emissiveな属性を持つマテリアル(材質)を持つオブジェクトという物があります。
例えばStandardAssetsの場合、Emissiveが設定されていて、かつLightmapのstaticが入ったオブジェクトであれば、発光します。


Emissiveの特性
EmissiveなオブジェクトはAreaLightと異なり、GIモードがRealtimeモードならばランタイム時に光の強度や色を変更する事が出来ます。
ただ、基本的にEnlitenのRealtime GI Resolutionベースで光源を設定しているので、Realtimeモードの場合はAreaLightと比較して光の表現が雑です。

AreaLightと似たような特性
雑ではありますが、AreaLightと同様に広い範囲から照射すればフワッとした、狭い範囲から照射すれば割とハッキリとした影が表現されます。
また静的(static)なオブジェクトにしか影や光源が反映しないのも同様です。基本的に動的に動かすオブジェクトに影響を与えたい場合、Lightprobe様が大活躍します。

また、マテリアルのGIモードをBakedに設定し、Final Gatherを設定すると、AreaLightと比較して殆ど見分けがつかないレベルの光が表現出来ます。
発光する範囲と形状
Emissiveなオブジェクトの優位性の一つは、テクスチャでマスクを設定したり、複雑な範囲は形状から発光出来る点です。
Emissiveな項目にテクスチャを設定すると、光が漏れないようにマスクを掛けたり、光の色にフィルターをかけるような表現が出来ます。

また、マテリアル単位で光るので、複雑な…例えば蛍光灯やネオンのような表現も出来たりします。Arealightは基本的に四角で表現するので、複雑な形状を表現したい場合には若干有利です。

で、どっちが良いの?
個人的にはEmissiveなオブジェクトの方が使いやすいといえば使いやすいです。
ただしRealtimeGIベースは表現が割と汚くなりやすく、しかしてBaked&FinalGatherを使用するとライトを焼くのに猛烈に時間がかかるので、その辺りがネックになります。
個人的な使い分けとしては、広範囲にやるならAreaLight、蛍光灯等の細かいパーツならEmissiveオブジェクト、輝度があまり高くなくうっすらと光る程度ならEmissiveといった感じです。
ちなみにUnity 5.6b6にProgressive Lightmapperという、「任意の範囲を優先して焼く&EmissiveをRealtimeGIベースじゃなくす」機能を持ったライティングモードが追加されるので、ある意味Emissiveの問題は回避は出来るといえば出来るようになるかもしれません。

シーンビューで見てる位置を優先して、粗いライティングから収束していく感じでライトを焼いてくれます。広いマップでも見てる範囲を優先して焼いてくれるので、確認したい範囲をサクサクっと確認出来て便利
関連
【Unity】コンポーネントのイベント実行順についてのTips
GameObjectにアタッチしたスクリプトの実行順番は、特に何もしなければ割とランダムです。今回はその辺りについて少し整理します。
スクリプトの実行順番
UnityはコンポーネントをGameObjectに設定すればコンポーネントに記述したイベントを呼び出してくれます。自動的に呼ばれる代表格はAwakeやOnEnable、StartやUpdate等です。

若干面倒くさい事に、このコンポーネントの処理実行順は特に設定しなければ不透明…というか、どの順番で呼ばれるかは分かりません。
たとえばマネージャークラスのような物よりも先に末端のコンポーネントが先に呼ばれるといったケースも有りえます。
スクリプトの実行順を制御する
一応、スクリプトの実行順番は、Script Execution Orderのキーワードで設定する事が出来ます。
Script Execution OrderをGUIで設定
一番GUI的なのはScript Execution OrderのUIで書き換える事です。
実行順は、上が優先度が高く下が低いです。
正確には、数値が低い方が優先されます。標準のコンポーネントは実行順は0です。


なお、一覧表示中にコンポーネントの頭文字のキーを押すと、該当のスクリプトまで選択がジャンプします。一つしか無い場合はその瞬間に選択が確定します。

メタデータに直接書き込む
スクリプトの量が多くなってくると、Script Execution Orderでは設定が面倒くさくなってきます。そんな時の力技は.metaを直接書き換えてしまうアプローチがあります。
Script Execution Orderの情報は各スクリプトのメタデータに有ります。
metaを開いて、 executionOrderの指定する数値を書き換えます。無ければ追加します。
スクリプト単位で書き込めるので、手軽といえば手軽に設定できます。


DefaultExecutionOrderを使用
一方、スクリプト側から設定する方法も(多分)5.5辺りから追加されてるっぽいです。*1
コンポーネントのAttributeとして設定すると、指定のコンポーネントの実行順を制御します。またScript Execution Orderと同様、数値が低い方が優先され、標準コンポーネントの実行順は0です。
なおScript Execution Orderが優先されます。

イベントの実行順
イベントの実行順ですが、Unity - マニュアル: イベント関数の実行順に絵付きで分かりやすく書いてあります。
要するに、
- Awake
- OnEnable
- Start
- Update
の順で呼ばれます。但し、StartとUpdateはインスタンス化直後ではなく、スタートのタイミングで呼ばれます。
- Awake
(シーンに配置orAddComponent直後
GameObjectがActive時) - OnEnable
(シーンに配置orAddComponent直後
ComponentがEnable時) - Start
(他のStartと同時) - Update
(他のUpdateと同時)
つまりコンポーネントやオブジェクトを生成したタイミングで即座にAwake→OnEnableが呼ばれ、他の全てのAwakeとOnEnableが呼ばれた後にStartが呼ばれ始めます。
OnEnableとAwakeの違い
一見一気に呼ばれるAwakeとOnEnableですが、よく見ると若干挙動が異なります。
Awake: この関数は常に Start 関数の前およびプレハブのインスタンス化直後に呼び出されます。(もしゲームオブジェクトがスタートアップ時に無効である場合、有効化にされるまで Awake は呼び出されません。)
OnEnable: (オブジェクトがアクティブな場合にのみ呼び出されます): この関数は、オブジェクトを有効にした直後に呼び出されます。例えば、MonoBehaviour インスタンスが作成されたとき、レベルロードあるいはスクリプトコンポーネントのアタッチされたゲームオブジェクトがインスタンス化されたときに実行します。
要するに、
Awake:
OnEnable:
つまりGameObjectのインスタンス化後、コンポーネントがdisableでもAwakeは呼ばれ、enable時にOnEnableが呼ばれるという事です。

これを上手く使えば、階層の有るPrefabのような場合、GameObjectのアクティブ/非アクティブやコンポーネントのenable/disableを上手く使うと、先に全てのAwakeを実行してからOnEnableを実行するといった事も出来なくは無いかもしれません。
ScriptableObjectのOnEnableは、大抵Awakeより先に呼ばれる
ScriptableObjectをシリアライズしている場合、参照先のScriptableObjectのOnEnableが呼ばれるタイミングは、他のAwakeよりも早いです。
- シーンに参照があれば、まず呼ばれる
- シーンが参照するPrefabから参照されていたら呼ばれる
- Instantiateで生成する前に参照を辿って呼ばれる
- PreloadAssetsに登録されていればシーン読み込む前に呼ばれる
ただし、エディターで操作中に意図せずOnEnableが呼ばれる事もあります。
Execution Orderが効かないケース
残念ながら、Execution Orderが効かないケースもあります。
と言うより、Execution Orderはどうも「生成時にコンポーネント呼出順を並べる機能」っぽく、逐次生成すると効果を発揮しないみたいです。
なので、下のような現象が発生します。
コンポーネントやオブジェクトを動的に追加した場合は、生成順になる
動的にコンポーネントを生成した場合、コンポーネントの実行順は(StartやUpdate等も)オブジェクトの生成順になります。
例えば下のようなコードが合った場合、Execution Orderを設定してもStartやUpdateの呼出順はScript1が先、Script2が後になります。

同様に、これがGameObjectの生成であった場合も、先に生成されたGameObjectのStart、Updateが優先されます。
Script2がScript1より優先的に実行される状況を作っても、Script1がアタッチされているオブジェクトを先に生成すれば、StartはScript1が先に呼ばれます。


しかし”同時に”生成した場合は、Script Execution Order準拠
この生成した場合のルールですが、複数のコンポーネントがアタッチしているやPrefabの子オブジェクトにアタッチされているといった状況で、一気に複数のオブジェクトを生成出来る場合、Execution Orderが適応されます。



関連
旧記事
*1:何故多分かと言えば、マニュアルに書いて無いからです。自分も5.6の新しいNavmesh機能のサンプル(ランタイムにNavmeshを構築するやつ)に使われてた時に気づきました。
【Unity】Statemachinebehaviourの処理の実行順について

Statemachinebehaviourをステートに貼り付けた際、Statemachinebehaviourはどのような順番で呼ばれるのか。
確認してみました。
Statemachinebehaviourを呼ばれる順番
ルールは、どうも下の通りっぽいです。
- 親ステートが子ステートよりも先に呼ばれる
- 上に配置したStatemachinebehaviourが下のStatemachinebehaviourより先に呼ばれる
- 上にあるレイヤーが下にあるレイヤーより先に呼ばれる

SubStateMachineのStatemachinebehaviour
意外と気づいてない人も居るかもしれませんが、SubStateMachineにもStatemachinebehaviourを設定する事が出来ます。

その場合、OnStateMachineEnterが「SubStateMachineに到達した時に呼ばれる処理」で、「OnStateEnter」が子ステートマシンで変化が合った際に呼ばれます。
たとえば下のような図のステートとStatemachinebehaviourが合った場合、OnStateEnterはNewStateとHumanoidWalkが切り替わる度に、OnStateMachineEnterはトリガー「何らかの条件」が呼ばれ、AnyStateからStateMachineに切り替わる度に呼ばれます。


またSubStateMachineの子が現在のステートの場合、OnStateUpdateは常に呼ばれ続けます。
