Chronosを用いたポーズ処理の実装
概要
Chronos - Time ControlアセットをUnityのポーズ処理に使うやり方のメモ.
Unityのポーズ処理はこれといって決まったやり方が無く,地味に面倒.
調べると一番出てくるやり方はTime.timeScaleを0にする方法だが,
よほどシンプルなゲームでない限り,うまくいかない.
ポーズ中に一部のオブジェクトはポーズを無視させたいような状況が発生すると工夫が必要となる.
一般的にTime.timeScale=0以外だとUnity4/C# ポーズ処理の実装をどうするか考えた話 - Qiita に挙げられているような方法がよく使われている模様.
Chronosアセットについて
Chronos - Time Control - アセットストア
UnityでのTime controlをやりやすくするアセット. 動画で紹介されている機能は
- SLOW TIME
- PAUSE TIME
- REWIND TIME
- GROUP CONTROL
- OBJECT CONTROL
- AREA CONTROL
- PHYSICS CONTROL
- PHYSICS REWIND
ポーズ処理のみに使うにはオーバースペック感がすごい.
使い方
基本
Timekeeperコンポーネントを付けたTimekeeperオブジェクト(シングルトン)をシーンに追加する. 時間を操作したいグループ単位でGlobalClockコンポーネントを増やす.
GlobalClockは階層構造を持てる.
Parentで指定したGlobalClockが親になり,Timescaleの変化などが子に伝播する(どう扱うかをParent Blendで設定できる)
Clockの管理下にしたいオブジェクトにはTimelineコンポーネントをつける.
GlobalClockでTimekeeperに付けてあるGlobalClockの中のどれかを選べるようになっている.
Rewindableにチェックを入れるとRewindができるようになるが,多少メモリを余分に消費するらしい. ポーズ処理のみに使うのであればチェックを入れない方が良いかも.
timeScaleの設定
// Chronosを使わない場合
Time.timeScale = 0.0f;
// Chronosを使う場合
// keyはGlobalClockの名前
Timekeeper.instance.Clock(key).localTimeScale = 0.0f;
各オブジェクトからの時間情報の取得する際は, Timelineコンポーネントを介して取得する.
var timeline = GetComponent<Timeline>();
// timeScaleを取得
bool paused = timeline.timeScale == 0.0f;
// deltaTimeの取得
float dt = timeline.deltaTime;
Rigidbody
RigidbodyをChronosの管理下にしたい場合は,Timelineコンポーネントが持つRigidbodyTimeline3DクラスをRigidbodyの代わりに使う. 当然,Rigidbodyコンポーネントも付けておく必要あり.
var timeline = GetComponent<Timeline>();
// 速度の取得
Vector3 v = timeline.rigidbody.velocity;
// 力を加える
timeline.rigidbody.AddForce(f);
ポーズ処理
例えば,動きを止めたいグループのClockのみtimeScaleを0にするなど.
public static void pause() {
clockNamesToPause.ForEach(key => {
Timekeeper.instance.Clock(key).localTimeScale = 0.0f;
});
}