今回はTimelineで物理演算の結果を使用する方法について考えてみます。
Timelineという機能
Timelineは時間やシーケンスに関する表現を実現するための機能です。Animationやオーディオの再生、スクリプトの制御などなど。
現在*1はアニメーショントリガーが無く少し面倒な所もありますが、Scriptで拡張可能なので割と何とかなったりします。
ちなみにTimeline自体は意外と軽いです。ただエディター上だと超重く、ロード時間も長いです。ビルドすると軽く、ロードも大幅に短縮されます。
またTrackが増えすぎると重くなるので、複数のTimelineに分割するアプローチが求められます。
Timelineはゲームを再生しないから効率的
さて、Timelineの強みは間違いなくエディターを再生せず動作を確認できる事です。
この動作によりゲームの再生→確認→修正の回転を、確認→修正(リアルタイムに反映)まで落とし込めるので効率的に動きを調整出来る訳です。
特にパーティクルやオーディオのタイミングは、ミリ秒違うだけで印象が大きく変わります。この数ミリ秒を調整のために毎回数秒~数十秒待つのは間違いなく高いコストです。
Timelineをうまく活用することで、調整すべき事を短いサイクルで作れる訳です
物理演算の動きはゲームの再生を要求する
とは言え、幾つかのコンポーネントによって実現する動き…例えばRigidbodyが実現する物理の動き等はTimelineだけではなくゲームを再生しないと得られない結果があるのも事実です。
例えばコップの落下タイミングに合わせてモデルを差し替えて音を出す(スローモーション付き)みたいな事をやろうと思うと、結構面倒です。破片の動きなど入ったら嫌です。
物が吹き飛ぶ動きをアニメーションカーブで実現しろとか言われたら、笑えます。
大抵の項目はPlayableBehaviourを記述したりITimeControlの定義で何とかなりますが、それでは実現できない項目があるのも事実。
それを今回は何とか出来ないか考えてみます。
Timeline上で物理演算を動かす
アイディアその1として、Timeline上で(ゲームを再生せず)物理演算を進めるアプローチを考えてみます。
Physics.Simulateで物理演算を手前で進めてしまうアプローチです。
考え方は単純で、シーン内全てのRigidbodyを集めてリセット可能なポイントを用意、あとはTimelineの時間までシークすれば…というものです。
オブジェクトの収集タイミングは「Preview」になったタイミングなので、座標の調整時にはPreviewをOFFにして調整します。
物理演算の動きをAnimationClipに保存する
アイディアその2は、AnimationClipに物理演算の動きを保存してしまうアプローチです。
これは二つの利点があります。
- 高速(負荷は物理演算を回すよりもとても安い傾向にある)
- 再現性(ゲーム用物理演算は、全ての環境で同じ結果を出すとは限らない)
ただし動かすオブジェクトの対象が多すぎると、エディターでオブジェクトをバインドするのにとても長い時間を要求する事もあります(数分のレベル)
このAnimationClipへの保存は、GameObjectRecorderを使用します。
コードはマニュアルそのまま行けます…というか、ちょくちょく変化するので、マニュアルを見て下さい。
Unity - Scripting API: GameObjectRecorder
全てのオブジェクトを物理演算で動かす→最低10FPS、オブジェクトをGameObjectRecorderでClipに変換してTImelineで動かす→最低80FPS #unity pic.twitter.com/IcGqK0mcTP
— 椿 (@tsubaki_t1) 2018年5月4日
インタラクティブな要素が無い 演出目的 なら、物理演算ぶん回すよりClipに変換してTimelineなりAnimatorなりで再生した方が良い印象 pic.twitter.com/GHuiwIzN3q
— 椿 (@tsubaki_t1) 2018年5月4日
お蔵入り確定してますが、一応「Timelineで再生中の動きを保存する」奴も置いておきます。
gist:d9e867be84b6f71176a4cf451028e86b · GitHub
*1:Unity2018.1