6日目 - Unity④

時間

ゲームで時間を使いたいときはたくさんあります。

など

Unityでカウントするとなると一番に思いつくのはUpdate()で変数に+1し続けることだと思いますが、Update()は環境によってその実行間隔が変わるうえ、処理負荷によっても大きく変動します。

そこでUnityではUpdate()の実行間隔を取得する関数Time.deltaTimeを利用して時間を計測します。

GameManagerスクリプトに以下のコードを書きましょう

		//経過時間を求めるコード
		float time; //経過時間time
		
		void Start()
    {
		    time = 0; //ゲーム開始時にtimeを0で初期化
    }
    
    void Update()
    {
        time += Time.deltaTime; //前のUpdate()実行タイミングからの経過時間を足して累計時間を計算
        
        if(Keyboard.current.tKey.wasPressedThisFrame)
				{
						Debug.Log(time); //Tキーが押されたら現在の経過時間を表示
				}
    }

Tキーを押すと現在の経過時間を表示できます。

また、ゲーム開始時からの経過時間を取得する関数Time.timeもあります。

		//タイマーの実装
		float time, countStartTime;
		
		void Update()
    {
        if(Keyboard.current.tKey.wasPressedThisFrame)
				{
		        countStartTime = Time.time; //Tキーが押されたら現在の時間を記憶
				}
				
				if(Keyboard.current.tKey.wasPressedThisFrame)
				{
						time = Time.time - countStartTime; //Tキーが押されたら計測を開始した時間と現在の時間の差を計算
						Debug.Log(time); //計測時間を表示
		
    }

基本的に、短い時間の計測or一時停止したい場合はTime.deltaTimeを、長い時間の計測やシンプルにゲーム開始時からの経過時間を取得したいときはTime.timeを使用しましょう。

また、Time.deltaTimeにはもう一つの使い方があります。それは移動などを一定速度で行いたいときなどです。

Transformを使用した方法

		void Update()
    {
        transform.position = Vector3.forward * Time.deltaTime; //(0, 0, 1)に前進するのを一定速度にする
    }

Update()の間隔が長い時はTime.deltaTimeは0.033sとかになり(30fpsの場合)、足し算する値が少し大きめの値になります。一方Update()の間隔が短い時はTime.deltaTimeは0.0083sとかになり(120fpsの場合)、足し算する値が少し小さめの値になります。

これによってUpdate()の実行間隔に影響されずに常に一定のスピードで物体を移動させることができるようになります。

時間の速度・一時停止

シーン遷移

大きくゲームの要素が変わる場合(スタート画面やクリア画面、次のステージなど)は、ゲーム中にシーンそのものを移動することで簡単に実装することができます。

Unityの用語について

ゲームの終了シーンを制作します。

Scenesフォルダに移動。

Scenesフォルダで右クリックし、Create > Scene > Sceneを選択

EndSceneと名付ける。

image.png

image.png

シーンを遷移できるようにするには、使用するシーンをリストに追加する必要があります。

左上のFileからBuild Profilesを選択します。

image.png

開いたウィンドウの左上にあるScene Listタブを開く。

image.png

いまリストに追加されているのはデフォルトで制作されていたSampleSceneだけです。

ここにGameSceneとEndSceneを追加します。

Sceneファイルをドラッグアンドドロップで追加することができます。またAddOpenScenesを押すといま開いているシーンを追加できます。

gifr.gif

SampleSceneは今回使用しないのでリストから削除します。

カーソルを合わせて右クリックし、Remove Selectionを選択で削除できます。

また、右側にある番号がシーンの実行順序で、0番がゲーム開始時に再生されるシーンになります。(デバッグ中は開いてるシーンからスタート)

とりあえずGameScene→EndSceneの順にします。なっていない場合はドラッグアンドドロップで順序を入れ替えられます。

image.png

ゲームのシーンをスクリプトから遷移するには以下のコードを書きます。

SceneManager.LoadScene("Sceneの名前");

SceneManager.LoadScene(シーン番号); //SceneListの右側にある番号

一番上に

using UnityEngine.SceneManagement;

が追加されていないときは追加してください。

おそらくエディタが自動で補填しているはずです。

シーンをまたいで変数にアクセスする方法

練習

ゲーム開始から1分経ったらEndSceneに遷移するようにしよう。

(Time.deltaTimeの続きですGameManagerスクリプトに以下のコードを書きましょう

後にシーンを新たに追加する予定があるので、SceneManager.LoadScene()では番号ではなく名前でシーンを指定するようにしましょう。

デバッグ時は10秒とかでテストしたほうが楽だと思います。

UI

Debug.Logで出力した情報は実際にゲーム化したときに見ることができません。そのためゲーム画面内に出力する必要があります。

UIとはユーザーインターフェースの意味です。Unityでは文字や画像、ボタンなどをさし、プレイヤーがゲーム内の情報を得たり操作するのに必須の要素です。

image.png

いまのUnityにはUIを作るためにuGUIとUI Toolkitという主に2つのツールが用意されています。

uGUIは従来からある方法で、Canvasコンポーネントが付いたゲームオブジェクトに様々な種類の子オブジェクトを作成してUIを作る方法です。

一方UI Toolkitは最近正式版になったばっかりで、HTML/CSSに似たUXMLファイルを編集することでUIを表現し、それをUIDocumentコンポーネントにつけることでUIを表示します。GUIでUXMLファイルを編集できるUI Builderというツールも用意されています。

現在UnityはUI Toolkitの使用を推進していますが、今回のUnity勉強会ではuGUIを使用したUIの作り方を解説します。来年には移行しているかもしれません…

(私にUI Toolkitの知見がないのと、まだそこまで一般的ではなく情報が少ないこと、VRだとどうなるのかわからないのと、初心者には比較的難しい気がするため)

テキスト

Unityにはテキストの表示方法に2つの種類があります。

1つ目がLegacyでシンプルなテキスト表示方法ですが、ギザギザが見えたりカスタマイズがあまり自由ではありません。

2つ目がTextMeshPro(TMP)で、かなりいろいろカスタマイズすることができますが、少し手間もあります(特に日本語を使うとき)。

今回はほぼ標準になりつつあるTMPのほうを使用していきます。

GameSceneで作業します。

まずはHierarchyで右クリックをし、UI > Text - TextMeshPro を選択します。

image.png