うにty

Unityの一時停止で止まるもの、止まらないもの【Time.timeScale】


Unityの一時停止で止まるもの、止まらないもの【Time.timeScale】


こんにちは、技術部の下荒磯です。

Unityにおける一時停止といえば「Time.timeScale = 0 」ですが、いざ止めてみたらなんか動いてるやつがいるぞ…。
なんてことありませんか?

ws000612

Time.timeScale は時間の経過をスケールするためのプロパティです。
時間に依存しない処理は「止まらない」場合があるため、そこらへんをしっかり把握する必要があります。

サンプル①


いくつか例を見てみましょう。

例えば、以下の処理は「Time.timeScale = 0 」で止まりません。

	void Update() {
		Debug.Log("止まるのか?いや、止まらない!");
	}

一方、こちらの場合は止まります。

	void FixedUpdate() {
		Debug.Log("止まります!");
	}

つまり
・Update関数は、「Time.timeScale = 0 」にしても止まりません。
・FixedUpdate関数は、「Time.timeScale = 0 」で止まります。(関数が呼び出されない)

そもそもUpdateが止まっちゃったら、入力すら受け付けなくなっちゃうので、timeScaleを1に戻せないですよね。

サンプル②


もう一つ例を見てみましょう。今度は両方ともUpdateでの処理です。

こちらの処理は止まります。

	void Update() {
		GetComponent<Rigidbody>().velocity = new Vector3(1.0f, 0, 0);
	}

※Update内でGetComponentをしていますが、本来はStartでやる方が良し。

一方、こちらの処理は止まりません。

	void Update() {
		transform.Translate(1.0f, 0, 0);
	}

Rigidbodyへの操作は、フレーム経過時間が加味されるため、Update内に記述しても止まります。
(※本来、物理演算はFixedUpdateに記述すべきですが、今回は突っ込まない方向で)
しかし、Transformへの操作は、上記の記述ではフレーム経過時間が加味されていないため、止まりません。

そもそもですが、Update内における描画に影響するような操作(座標の変更など)は、実行環境によるフレームレートの違いを補うために、フレーム経過時間を加味した記述にすべきです。

したがって、以下のように記述します。

	void Update() {
		transform.Translate(1.0f * Time.deltaTime, 0, 0);
	}

上記の様に記述しておけば、移動量に前フレームからの経過時間が乗算されるため、「Time.timeScale = 0」となった時には、ちゃんと止まるようになります。

まとめ


「Time.timeScale = 0 」による一時停止は
・Updateは止まる。
・FixedUpdateは止まらない。
・Update内でも、時間を加味していない処理は止まらない。
・物理演算はどこに記述しても強制的に止まる。

以上のことを踏まえたうえで、効率的に利用してきましょう。


こちらの記事もおすすめです。
Unityのマイナーだけど便利な関数を使ってみた【Vector3.SmoothDamp】
Unityで動く床を実装するときにハマる罠とその解決方法
UnityのVector3について勘違いしていたこと

最後までお読みいただきありがとうございます。
← Unityの記事一覧にもどる

  • このエントリーをはてなブックマークに追加

PAGE TOP