【Unity】【Cinemachine】衝撃を受けたらカメラをシェイク(振動)させるImpulse機能を使う

Cinemachineで衝撃を受けたらカメラを振動させるImpulse機能の使い方をまとめます。

Unity2018.4.0
Cinemachine2.2.9

はじめに

この記事ではCinemachineの拡張機能であるImpulse機能について説明します。

Cinemachineの基本的な使い方やVirtual Cameraの設定方法は本記事では説明しません。
これらは以下の記事にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

Impulse機能とは?

CinemachineのImpulse機能を使うと、物体同士がぶつかって衝撃が発生したときにカメラを揺らす表現ができます。

f:id:halya_11:20190630235148g:plain

振動の発生のさせ方は二通り用意されています。
Cinemachine Collision Impulse Sourceを使えばRigidbodyの衝突に応じて振動を発生させてくれます。
スクリプトから振動の発生を制御したい場合にはCinemachine Impulse Sourceを使います。

とりあえず振動させてみる

それではとりあえずカメラを振動させてみます。

まずは振動を発生させる側の設定です。
適当なRigidbodyにCinemachine Collision Impulse Sourceをアタッチします。

f:id:halya_11:20190630235642p:plain

Sinal ShapeのRaw Signalには歯車アイコンからPresets > 6D Shakeをアサインしておきます。
Amplitude GainとFrequency Gainには振幅と振動数の倍率を入力します。
(これらは初期値でもいいですが、振動が小さかったらここを触ってみてください)

f:id:halya_11:20190701000011p:plain

次にVirtual Cameraの設定です。
Virtual Camera最下部のExtensions > Add ExtensionからCinemachine Impulse Listenerを選んでアタッチしてください。

f:id:halya_11:20190701000241p:plain

これでカメラが振動を受け取れるようになりました。
適当にRigidbodyが衝突を行うようにして再生してみます。

f:id:halya_11:20190701000435g:plain

これでとりあえず振動するようになりました。

振動する時間を設定する

次に振動する時間を設定します。
振動時間はCinemachine Collision Impulse SourceのTime Envelopeから設定できます。

f:id:halya_11:20190701000709p:plain

Attackには最大振幅に達するまでのカーブと時間を設定できます。
これを設定すれば徐々に振動が強くなっていくような表現ができます。

Substain TimeはAttackの後に最大振幅を維持する時間です。
Decayは最大振幅から徐々に揺れが収まるまでのカーブと時間です。

また、Scale With Impactにチェックを入れると衝撃が大きいほど振動時間が伸びます。

影響範囲を設定する

次に振動の影響範囲を設定します。
影響範囲はCinemachine Collision Impulse SourceのSpatial Rangeから設定できます。

f:id:halya_11:20190701001005p:plain

Impact Radiusは振動が減衰せずそのまま伝わる半径です。
そこからDissipation Distanceまでは徐々に減衰していきます。
つまりImpact Radius + Dissipation Distanceが振動の影響範囲です。

また、Dissipation Modeを指定すると振動の減衰方法を下記のように指定できます。

名前 説明
Linear Decay 線形に減衰していく
Soft Decay 減衰し始めと減衰の最後の方で変化量が滑らかになる
Ease In Out Sineみたいなイメージ(あくまでイメージ)
Exponential Decay 減衰し始めほど変化量が大きい

重いほど / 速いほど振動を強くする

一般的に物体は重いほど、また速度が大きいほどぶつかった時の衝撃は大きいです。
そこで物体の重さを振動に影響させるにはCinemachine Collision Impulse SourceのScale Imparct With Massにチェックを入れます。
速さを振動に影響させるにはScale Impact With Speedにチェックを入れます。

f:id:halya_11:20190701002310p:plain

なおUse Impact Directionは衝撃が与えられた方向を振動に影響させるオプションのようですが、効果がいまいちわかりませんでした。

振動の発生条件をフィルタリングする

Cinemachine Collision Impulse SourceのTarget Object Filterを使うと、振動の発生条件をフィルタリングできます。

f:id:halya_11:20190701002740p:plain

Layer Maskを設定すれば、そのレイヤーマスクのオブジェクトに当たった時にだけ振動が発生します。
またIgnore Tagに設定されたタグが設定されたGame Objectには衝突しても振動が発生しません。

特定のカメラにだけ振動を伝える

特定のカメラにだけ振動を伝えるにはImpulse Channelを使います。

まずVirtual CameraのCinemachine Impulse ListenerでChannel Maskを設定します。
これを設定することで、このChannelに伝わってきた振動だけを受け取ることができます。

f:id:halya_11:20190701003116p:plain

次にCinemachine Collision Impulse SourceのImpulse Channelを変更します。
これにより、発生した振動はそのChannelにだけ伝わります。

f:id:halya_11:20190701003049p:plain

Rigidbodyを使わずに振動を発生させる

さてこれまではCinemachine Collision Impulse Sourceを使って、Rigidbodyによる衝突検知時に振動を発生させました。
Rigidbodyを使わずに振動を発生させるにはCinemachine Impulse Sourceを使います。
これを適当なGameObjectにアタッチし、GenerateImpulse()を呼ぶことで振動を発生させられます。

var source = GetComponent<Cinemachine.CinemachineImpulseSource>();
source.GenerateImpulse();

細かい設定項目はCinemachine Collision Impulse Sourceと被っているので説明を割愛します。

f:id:halya_11:20190701003919p:plain

参考

docs.unity3d.com

docs.unity3d.com

docs.unity3d.com