Version: 2021.1
ScriptableObject
Important Classes - Mathf

Important Classes - Time and frame rate management

The Time Class

Unity’s Time class provides a number of important basic properties which allow you to work with time-related values in your project.

The descriptions for each member of Time script reference page are self explanatory, and that is the best place to learn about them.

Listed here is a small selection of examples to provide an idea of the common and typical uses:

Time.time returns the amount of time since your project started playing.

Time.deltaTime returns the amount of time that elapsed since the last frame completed.

Time.timeScale represents the rate at which time elapses. You can read this value, or set it to control how fast time passes, allowing you to create slow-motion effects.

For the full list of time-related properties, see the Time script reference page.

Frame rate management

The Update function allows you to monitor inputs and other events regularly from a script and take appropriate action. For example, you might move a character when the “forward” key is pressed. An important thing to remember when handling time-based actions like this is that the game’s frame rate is not constant and neither is the length of time between Update function calls.

この例として、フレームごとに、徐々に前方にオブジェクトを動かす作業を考えて見ましょう。最初は、フレームごとに一定の距離ずつオブジェクトを移動しているように見えるかもしれません。

//C# script example
using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public float distancePerFrame;
    
    void Update() {
        transform.Translate(0, 0, distancePerFrame);
    }
}

しかし、フレーム時間が一定でないので、オブジェクトは不規則な速度で移動するように見えます。フレーム時間が 10 ミリ秒なら、オブジェクトは 1 秒に distancePerFrame の距離を 100 回前進します。しかし、フレーム時間が 25 ミリ秒に増加した場合 (例えば CPU 負荷のため) 1 秒に 40 回しか前進できず、進む距離が少なくなります。その解決方法は、フレーム時間に応じた移動の距離をスケーリングすることです。移動の距離は Time.deltaTime プロパティーから読み取り可能です。

//C# script example
using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public float distancePerSecond;
    
    void Update() {
        transform.Translate(0, 0, distancePerSecond * Time.deltaTime);
    }
}

Note that the movement is now given as distancePerSecond rather than distancePerFrame. As the frame rate changes, the size of the movement step will change accordingly and so the object’s speed will be constant.

Depending on your target platform, use either Application.targetFrameRate or QualitySettings.vSyncCount to set the frame rate of your application. For more information, see the Application.targetFrameRate API documentation.

Fixed Timestep

メインフレームの更新とは異なり、Unity の物理システムは、固定された時間ステップで更新されます。これはシミュレーションの正確さと一貫性にとって重要です。物理計算の更新開始時に、Unity は最後の物理計算の更新が終了する固定の時間ステップ値を時間に加えてアラームを設定します。物理システムは、アラームが切れるまで計算を実行します。

固定時間ステップのサイズは Time ウィンドウで変更することができ、スクリプトからTime.fixedDeltaTime プロパティーを使用して読み取ることができます。時間ステップの値が低いと物理演算の更新頻度が高くなり、より正確なシミュレーションが可能ですが、CPU 負荷が高くなります。物理エンジンに高い要求をしない限り、大抵、デフォルトの固定時間ステップを変更する必要はありません。

Maximum Allowed Timestep

The fixed timestep keeps the physical simulation accurate in real time but it can cause problems in cases where the game makes heavy use of physics and the gameplay frame rate has also become low (due to a large number of objects in play, say). The main frame update processing has to be “squeezed” in between the regular physics updates and if there is a lot of processing to do then several physics updates can take place during a single frame. Since the frame time, positions of objects and other properties are frozen at the start of the frame, the graphics can get out of sync with the more frequently updated physics.

当然、CPU のパワーは非常に限られていますが、Unity は物理演算にかかる時間を効果的に遅くしてフレーム処理を追いつかせることができます。Maximum Allowed Timestep 設定 (Time ウィンドウ内) は、Unity が物理演算を処理するのに費やす時間と、特定のフレーム更新中に FixedUpdate の呼び出しを行う時間の制限を設定します。フレームの更新が Maximum Allowed Timestep よりも処理に時間がかかる場合、物理エンジンは “時間を停止” し、フレーム処理が追いつくようにします。フレームの更新が終了すると、物理演算の効果は停止してから時間が経過していないかのように再開します。この結果、リジッドボディは通常のようにリアルタイムで完全には動かず、わずかに減速します。ただし、物理効果の “クロック” は、それが正常に動いているかのように追跡します。物理時間が遅くすることは、一般的に目立つものではなく、ゲームのパフォーマンスに対して許容範囲の犠牲です。

Time Scale

「bullet-time」のような特殊効果のために、ゲームの時間の経過を遅くして、アニメーションやスクリプトの応答を少ない割合で発生させることは、有効な場合があります。さらに、ゲームを中断するときのように、完全にゲーム時間を凍結したい場合があるかもしれません。Unity は、リアルタイムと関連づけてゲーム時間をどのように進行させるかについて制御する Time Scale プロパティーを持っています。スケールを 1.0 に設定すると、ゲームの時間はリアルタイムに一致します。2.0 の値では Unity で 2 倍の速さで時間が経過します (つまり、アクションは、高速化されます)。他方、0.5 の値ではゲームを半分の速度に遅くします。0 の値は時間を完全に「停止」します。タイムスケールは、実際に実行を遅くするわけではなく、単に Time.deltaTimeTime.fixedDeltaTime を通して Update と FixedUpdate 関数に知らせる時間ステップを変えているにすぎません。Update 関数は、ゲーム時間が遅くなるとき通常より頻繁に呼び出される傾向がありますが、単に、各フレームに伝えられる デルタタイム の処理が減らされます。他のスクリプト関数はタイムスケールから影響を受けません。ですから、例えば、ゲームが停止している場合は、正常なインタラクションで GUI を表示できます。

Time ウィンドウには、グローバルにタイムスケールを設定できるプロパティーがありますが、一般的に、Time.timeScale プロパティーを使用してスクリプトから値を設定すると、より便利です。

//C# script example
using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    void Pause() {
        Time.timeScale = 0;
    }
    
    void Resume() {
        Time.timeScale = 1;
    }
}

Capture Framerate

A very special case of time management is where you want to record gameplay as a video. Since the task of saving screen images takes considerable time, the usual frame rate of the game will be drastically reduced if you attempt to do this during normal gameplay. This will result in a video that doesn’t reflect the true performance of the game.

Fortunately, Unity provides a Capture Framerate property that lets you get around this problem. When the property’s value is set to anything other than zero, game time will be slowed and the frame updates will be issued at precise regular intervals. The interval between frames is equal to 1 / Time.captureFramerate, so if the value is set to 5.0 then updates occur every fifth of a second. With the demands on frame rate effectively reduced, you have time in the Update function to save screenshots or take other actions:

//C# script example
using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    // Capture frames as a screenshot sequence. Images are
    // stored as PNG files in a folder - these can be combined into
    // a movie using image utility software (eg, QuickTime Pro).
    // The folder to contain our screenshots.
    // If the folder exists we will append numbers to create an empty folder.
    string folder = "ScreenshotFolder";
    int frameRate = 25;
        
    void Start () {
        // Set the playback frame rate (real time will not relate to game time after this).
        Time.captureFramerate = frameRate;
        
        // Create the folder
        System.IO.Directory.CreateDirectory(folder);
    }
    
    void Update () {
        // Append filename to folder name (format is '0005 shot.png"')
        string name = string.Format("{0}/{1:D04} shot.png", folder, Time.frameCount );
        
        // Capture the screenshot to the specified file.
        Application.CaptureScreenshot(name);
    }
}

一般的にこの技術を使用して動画を記録するのは非常に有効のようですが、著しく遅くなると、ゲームをプレイすることが難しくなります。テストプレーヤーの仕事を困難にしないよう十分なレコーディング時間を可能にするために Time.captureFramerate 値を試してみると良いでしょう。

ScriptableObject
Important Classes - Mathf