イベント関数
ゲームオブジェクトの作成および削除

タイムとフレームレートの管理

Update 関数を使用すると、定期的にスクリプトからの入力やその他のイベントをモニターして、適切な処置を取ることができます。例えば、Forward キーが押されるとキャラクターが動くとします。このような時系列のアクションを取り扱う場合、ゲームのフレームレートは一定ではなく、 Update 関数の呼び出しの時間的な間隔も一定ではないということに気を付けてください。

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

//C# の例
using UnityEngine;
using System.Collections;

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


//JS の例
var distancePerFrame: float;

function Update() {
    transform.Translate(0, 0, distancePerFrame);
}

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

//C# の例
using UnityEngine;
using System.Collections;

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


//JS の例
var distancePerSecond: float;

function Update() {
    transform.Translate(0, 0, distancePerSecond * Time.deltaTime);
}

ここでの移動は distancePerFrame ではなく distancePerSecond で与えられていることに注意してください。フレームレートの変化に応じて移動距離が変わるため、オブジェクトの速度は一定になります。

固定時間ステップ

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

You can change the size of the fixed timestep from the Time window and you can read it from a script using the Time.fixedDeltaTime property. Note that a lower value for the timestep will result in more frequent physics updates and more precise simulation but at the cost of greater CPU load. You probably won’t need to change the default fixed timestep unless you are placing high demands on the physics engine.

最大許容時間ステップ

固定時間ステップは、リアルタイムで物理シミュレーションを正確に保ちます。しかし、ゲームで物理演算を多用する場合、場合によっては問題を引き起こす可能性があり、ゲーム時のフレームレートも低くなってしまいます (例えば、ゲームにオブジェクト数が多い場合など)。メインフレームの更新処理は、通常の物理演算更新の間に「詰め込む」必要があります。そのため、実行する処理が大量にある場合は、いくつかの物理演算更新が 1つのフレーム内で行われます。フレームタイム、オブジェクトの位置、他のプロパティーがフレームの開始時に凍結されるため、グラフィックスは頻繁に更新される物理演算と同期状態ではなくなります。

Naturally, there is only so much CPU power available but Unity has an option to let you effectively slow down physics time to let the frame processing catch up. The Maximum Allowed Timestep setting (in the Time window) puts a limit on the amount of time Unity will spend processing physics and FixedUpdate calls during a given frame update. If a frame update takes longer than Maximum Allowed Timestep to process, the physics engine will “stop time” and let the frame processing catch up. Once the frame update has finished, the physics will resume as though no time has passed since it was stopped. The result of this is that rigidbodies will not move perfectly in real time as they usually do but will be slowed slightly. However, the physics “clock” will still track them as though they were moving normally. The slowing of physics time is usually not noticeable and is an acceptable trade-off against gameplay performance.

タイムスケール

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

The Time window has a property to let you set the time scale globally but it is generally more useful to set the value from a script using the Time.timeScale property:

//C#の例
using UnityEngine;
using System.Collections;

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

//JS の例
function Pause() {
    Time.timeScale = 0;
}

function Resume() {
    Time.timeScale = 1;
}

キャプチャーフレームレート

ゲームをビデオとして記録したいケースは時間管理の非常に特別なケースです。画面を保存する作業にはかなりの時間がかかるため、通常のゲーム中にこれを行おうとすると、ゲームの通常のフレームレートは大幅に削減されます。これではゲームの真の性能を反映しない動画になってしまいます。

Unity はこの問題を回避することができるCapture Framerate プロパティーを提供しています。プロパティーの値が 0 以外の値に設定されている場合、ゲームタイムは遅くなり、フレーム更新は正確な一定の間隔で行われます。フレーム間の間隔は、1/(Time.captureFramerate) に等しく、5.0 に値が設定される場合、更新が 1/5 秒ごとに発生します。フレームレートへの要求を効果的に削減すると、Update 関数の時間で、スクリーンショットを保存したり、他の操作を実行できます。

//C# の例
using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    //スクリーンショットシーケンスとしてフレームをキャプチャ。     
        //画像はPNGファイルとしてフォルダーに格納。これらの画像は
    // 画像ユーティリティソフトウェア (QuickTime Pro など) で動画と統合されます。
    // スクリーンショットを格納するフォルダー。
    // フォルダーが既存の場合、数を加え空のフォルダーを作ります。
    string folder = "ScreenshotFolder";
    int frameRate = 25;
        
    void Start () {
        // 再生のフレームレートを設定 (これ以降は、実際の時間はゲームの時間と関連しません)
        Time.captureFramerate = frameRate;
        
        // フォルダーを作成
        System.IO.Directory.CreateDirectory(folder);
    }
    
    void Update () {
        // ファイル名をフォルダー名に追加 (形式は "0005 shot.png")
        string name = string.Format("{0}/{1:D04} shot.png", folder, Time.frameCount );
        
        // 指定したファイルにスクリーンショットをキャプチャ
        Application.CaptureScreenshot(name);
    }
}

//JS の例
//スクリーンショットシーケンスとしてフレームをキャプチャ
//画像はPNGファイルとしてフォルダーに格納。これらの画像は
// 画像ユーティリティソフトウェア (QuickTime Pro など) で動画と統合されます。
// スクリーンショットを格納するフォルダー。
// フォルダーが既存の場合、数を加え空のフォルダーを作ります。
var folder = "ScreenshotFolder";
var frameRate = 25;


function Start () {
    // // 再生のフレームレートを設定 (これ以降は、実際の時間はゲームの時間と関連しません)
    Time.captureFramerate = frameRate;

    // フォルダーを作成
    System.IO.Directory.CreateDirectory(folder);
}

function Update () {
    // ファイル名をフォルダー名に追加 (形式は "0005 shot.png")
    var name = String.Format("{0}/{1:D04} shot.png", folder, Time.frameCount );

    // 指定したファイルにスクリーンショットをキャプチャ
    Application.CaptureScreenshot(name);
}

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

イベント関数
ゲームオブジェクトの作成および削除