スケールされない時間
CoddyのUnityジャーニー「本格的なゲームを作る」セクションの一部。レッスン 36/60。
ゲームが一時停止中またはスローモーション中でも、一時停止メニューのアニメーション、ゲーム再開前のカウントダウン、自動で解除される必要があるフリーズなどには、実時間の時計が必要です。Time.unscaledDeltaTimeは前のフレームからの実時間で、Time.timeScaleの値にかかわらず一定です。また、Time.unscaledTimeはゲーム開始からの実時間です。この一時停止メニューでは実時間を使ってローディングホイールを回すため、ゲームが一時停止中でもホイールは回転します。
void Update()
{
wheel.Rotate(0f, 0f, -180f * Time.unscaledDeltaTime); // 一時停止中かどうかに関係なく、毎秒半回転
}コルーチンにも同じ2種類があります。WaitForSecondsはゲーム内時間を数えるため、Time.timeScale = 0では終了しません。一方、WaitForSecondsRealtimeは実時間の秒数を数えます。メニューを開いたときに開始すると、このコルーチンはメニューのタイトルを0.5秒ごとに点滅させます。
IEnumerator Blink()
{
while (true)
{
title.SetActive(!title.activeSelf);
yield return new WaitForSecondsRealtime(0.5f);
}
}ゲームが停止したときに停止すべきゲームプレイにはスケールされた値を使い、一時停止中やスローモーション中にも動作させる必要があるもの、つまりメニューやそのアニメーション、一時停止を終了させるタイマーにはスケールされていない値を使いましょう。Invokeには実時間版がなく、常にゲーム内時間を数えます。
チャレンジ
中級金床にヒットストップを付けましょう。着地したとき、ゲーム全体が一瞬停止します。
Anvil.csでIEnumerator HitStop()を記述します。まずTime.timeScale = 0f;、次にyield return new WaitForSecondsRealtime(freezeTime);を記述し、その後1fに戻します。StartCoroutine(HitStop());を呼び出すvoid OnCollisionEnter(Collision collision)を記述します。
「プレイ」を押し、Spaceキーで金床を落とします。着地するたびにゲームが0.3秒間停止します。その後、「確認」を押します。
自分で試してみよう
using System.Collections;
using UnityEngine;
public class Anvil : MonoBehaviour
{
public float freezeTime = 0.3f;
// 金床が何かに当たったとき、ゲームを実時間でfreezeTime秒間停止する
}
本格的なゲームを作るのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド