top of page

3Dアクションゲーム編

Lesson5 シーンを作ろう

 タイトル画面、リザルト画面、ゲームオーバー画面を実装してそれぞれが適切な条件で遷移するようにします。このLessonでゲームは一通り完成なので頑張りましょう。

5-1

5-1 タイトル画面

5-1 タイトル画面

1

​Titleシーンの
​作成

 UnityではタイトルやインゲームなどをSceneというもので分けて、それぞれを繋げることができます。今まで制作してきたのはMainというシーンでした。タイトル、ゲームオーバー、リザルトのシーンを作成しましょう。

​ まずはタイトルのシーンを作ります。Scenesフォルダ内にSceneを作成してください。名前は「Title」にしておきます。この名前は後で参照するので間違えないように注意してください。

2

​タイトルシーンへ
​切り替える

 Titleシーンをダブルクリックするとライトとカメラだけのまっさらなシーンが開きました。

 インゲーム用のオブジェクトはMainシーンに配置していましたが、タイトル用のオブジェクトはTitleシーンに配置していきます。

3

タイトル画像用の
​パネルを追加

 ​UIからPanelを追加してください。​これは画面全体に引き伸ばされるシンプルな画像です。

4

タイトルの画像を
設定

 Source Imageに同梱したタイトル用の画像を設定しましょう。タイトル用の画像はSpriteフォルダに入っています。

​ デフォルトではA(不透明度)が100になっているので、255に変更して完全に表示されるようにしてください。

 これでタイトル画面の画像を設定できました。

​ Unityでは2Dの画像をSpriteと呼びますので、この教材でも今後はスプライトと呼称します。

5-2

5-2 ゲームオーバー画面

5-2 ゲームオーバー画面

1

GameOverシーン
​の作成

 次はゲームオーバー画面を作ります。

 Titleシーンと同じようにGameOverシーンを作成してください。このシーンの名前も後から参照するので間違えないように注意してください。

​ GameOverシーンにPanelを配置して、GameOverの画像を設定してください。

5-3

1

Resultシーンの
作成

2

Imageの配置

5-3 リザルト画面

5-3 リザルト画面

 最後にリザルトを作ります。

 Resultシーンを作成してください。このシーンの名前も後から参照します。

​ 今回はPanelではなくImageを用いてクリア画像を表示しましょう。

 位置とサイズを自由に調整して、クリア画像を設定してください。

3

背景画像の追加

 リザルトは他と違って、ゲームクリアの文字の画像しか用意していません。背景の画像は皆さんが用意してみてください。好きな画像でOKです。

​ 追加したい画像をSpriteフォルダ内にドラッグ&ドロップしてください。

4

スプライトへ変換

 このままではUIに使えないのでスプライトに変換します。

 追加した画像を選択して、TextureTypeを「Sprite(2D and UI)」に変更してください。

5

背景の追加

 変換できたら後は今までと同じようにUIに追加するだけです。Panelを追加して画像を設定してください。

​ UIの描画順はヒエラルキー内の順番に依存しています。ヒエラルキー内で下にあるUIオブジェクトが前面に表示されます。ヒエラルキーの順番を変えたい時はドラッグ&ドロップで動かしてください。

6

クリアタイムの
​UIを追加

 クリアタイムを表示するテキストを追加します。TextMeshProを追加してください。

 内容は仮で「ClearTime 99:99」にしておきます。​位置や装飾はお任せするので、自由に配置してみてください。

​ 物足りない方は他にも画像を追加して構いません。オリジナルのリザルト画面にしてください。

5-4

5-4 クリア画像を動かす

5-4 クリア画像を動かす

1

アニメーションの
​作成

 これで一応各シーンは完成しましたが、少し物足りないのでクリア画像を動かしてみましょう。

 画像を動かす、となるとスクリプトを書くことを考えた人もいるかもしれません。しかしUnityでは簡単な動きであればAnimatorを用いて実装することができます。

 AnimationフォルダにAnimationを追加してください。

2

アニメーションの
​アタッチ

 作成したアニメーションをクリア画像にドラッグ&ドロップしてください。Animator Controllerが自動で作成されたらOKです。

3

アニメーション
​ウィンドウを開く

 作成したアニメーションをダブルクリックするとアニメーションウィンドウが開きます。この状態でインスペクターからクリア画像を選択すると、クリア画像にアニメーションを設定することができます。

4

プロパティを追加

 アニメーションさせる項目はAdd Propertyで追加できます。項目を追加すると3dsMaxと同じようにキーを配置してアニメーションを作ることができます。

 座標だけでなく、大きさや回転なども扱えるので自由にアニメーションを作ってみてください。

5

キーを作成

 アニメーションウィンドウで右クリックして「Add Key」からキーを追加できます。
​ キーを編集するときは再生位置(白い縦線)を編集したいキーに合わせて、左側のプロパティから値を変更してください。

 左下のCurvesボタンを押すとカーブエディタに切り替わります。カーブ上をクリックしてキーを追加したり、カーブの形状を変えたりできます。

 アニメーションをループ再生したい場合はアニメーションを選択してLoopTimeにチェックを入れます。

 左上の再生ボタンでアニメーションを確認して、納得いくものができたらリザルトのUIは完成です。

​ 他の画像やテキストにアニメーションをつけても構いません。自由にリザルト画面を作ってみましょう。

5-5

5-5 シーンを繋げる

5-5 シーンを繋げる

1

シーンの関係を
​整理する

 これでMain(ゲーム部分)、Title、GameOver、Resultの4つのシーンが完成しました。適切なタイミングで4つのシーンを切り替えてみましょう。

​ シーン同士の関係は以下のようにします。

2

シーンをビルド
​対象にする

 シーンを繋げる前に、各シーンがビルド対象になるように設定します。

 新しく作ったシーンは最初はビルドされない設定になっており、スクリプトでそれぞれを繋ぐことができません。

​ File→Build Settingを選択してください。

 Add Open Scenesをクリックして、Main、Title、GameOver、Resultのシーンをビルド対象に設定してください(シーンを直接ドラッグ&ドロップしても可)

 ゲームを起動した時は一番上のシーンから始まります

​ 最初は当然タイトルから始まってほしいので、タイトルシーンを一番上に動かしてください。

3

タイトルから
​インゲームへ切替

 まずはタイトルからゲーム画面に遷移できるようにします。スぺースキーが押されたらシーンが切り替わるようにしましょう。

 先ほどの図を思い出してください。ゲームオーバーとリザルトからタイトルに戻る際にもスぺースキーを押してシーンを切り替える処理を実装する予定になっています。そのため、後から処理を使いまわせるように実装しましょう。

 新しいスクリプトSceneChangeを作成して以下のように入力してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;  // シーンを扱う時に必要

 

public class SceneChange : MonoBehaviour
{
    public string SceneName;    // 遷移先のシーン名

 

    void Update()
    {
        // スペースキーが押されたらシーンを切り替える
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SceneManager.LoadScene(SceneName);
        }
    }
}

【プログラムの解説】

​・TextMeshProの時と同じように、Sceneを扱う際は using UnityEngine.SceneManagement; を追加する必要があります。

・LoadScene関数でシーンを切り替えることができます。第一引数に遷移したいシーンの名前を入力することで遷移できます。

​ 名前以外にもシーン番号を入力しても遷移できます。

4

​シーン遷移用オブジェクトを追加

 SceneManager.GetActiveScene().name で現在のシーン名を取得できます。

 LoadScene(SceneManager.GetActiveScene().name); を実行することで、ステージを最初からやり直す機能なども簡単に実装できます(詳しい使い方は2Dアクションゲーム編にて!

Unity Tips!

 スクリプトが完成したらTitleシーン(タイトル)に空オブジェクトを追加して、SceneChangeをアタッチしてください。オブジェクト名は何でもOKです。

5

遷移先のシーン名
​を設定

 変数SceneNameをpublicにしているので、毎度のごとくインスペクターに表示されています。ここに遷移先のシーンの名前を入力しましょう。

​ タイトルから遷移したいのは当然メインなので「Main」と入力してください。

 これでタイトル画面でスぺースキーを押すとゲーム画面へ切り替わるようになりました。実際にゲームを実行して確認してみてください。

6

ゲームオーバーからクリアへの切替

 シーンを切り替えた際にライティングが適用されていない問題が発生した場合の対処法です。

 これはシーンの明るさを事前計算できていないことが原因になっています。

​ 「Window」→「Rendering」→「Lighting」を選択してライティングウィンドウを開いてください。Mainシーンを開いた状態で「Generate Lighting」をクリックしてください(Auto Generate にチェックが入っていた場合は外してください)

​ 実行してしばらくするとライトマップが作成され、シーンを切り替えても明るさが反映されるようになります。

 シーン上にオブジェクトが多いとかなり時間がかかりますが、その場合はシーン上にあるライト以外のオブジェクトを非アクティブにすることで短縮できます。

Unity Tips!

 次はゲーム画面からゲームオーバーとゲームクリアへの遷移を実装します。ゲームオーバーの条件は「体力が0になったら」、ゲームクリアの条件は「全ての星を集めたら」です。既にステージにある全ての星の数は取得しているので、それを使ってみてください。

 新しいスクリプトSceneChangeMainを追加して以下のように入力してください。青い部分は穴埋めなのでヒントを参考に埋めてみましょう。

【ヒント】④ は PlayerHitPoint 、 ⑤ は StarCountスクリプトも確認してみましょう!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// ① Sceneを扱う場合、追加する必要がある
(ここに入力)

 

public class SceneChangeMain : MonoBehaviour
{
    // ② PlayerHitPointを保存するpublicな変数(4-3を参考に!)
    (ここに入力)

 

    // ③ StarCountを保存するpublicな変数(4-3を参考に!)
    (ここに入力)

 

    void Update()
    {
        // ④ もしも体力が0以下になったらゲームオーバーシーンに遷移する
        (ここに入力)

 

        // ⑤ もしも集めた星の数と最大の星の数が同じになったら
        //   リザルトシーンに遷移する
        //   (それぞれの情報を取得する関数は実装済み!確認してみよう)

        (ここに入力)

 

    }

}

7

​必要なコンポーネントを関連付け

​ スクリプトが書けたらMainシーンのGameオブジェクトにアタッチしてください。

 ②と③で変数をpublicにしているので、ヒエラルキーから適切なオブジェクトをドラッグ&ドロップしてください。4-3を参考にしてみましょう。

8

タイトルに戻る
​処理を追加する

​ 体力が0になったらゲームオーバー画面に切り替わることと、星を全て集めたらリザルト画面に切り替わることを確認してみてください。

 最後はゲームオーバーとリザルトで「SPACEキーが押されたらタイトルに戻る」処理を実行するだけです。先ほど作成したSceneChangeスクリプトを使いましょう。

 ゲームオーバーシーンに新しい空オブジェクトを作成して、SceneChangeスクリプトをアタッチしてください。アタッチしたらインスペクターからSceneName(遷移先のシーン名)を「Title」に設定してください。

​ リザルトも同じように空オブジェクトを作成→SceneChangeスクリプトをアタッチ→シーン名を設定 という流れを行ってください。

​ これで全てのシーンが繋がり、ゲームを繰り返し遊べるようになったと思います。ゲームを実行して確認してみてください。

5-6

5-6 シーン越しに変数を共有

5-6 シーン越しに変数を共有

1

変数が破棄されないようにする

 これで一通り完成…と行きたいところですが、Resultシーンのクリアタイムが99:99のままになっています。

 しかしクリアタイムを計測しているのはMainシーンのGameTimerコンポーネントになります。シーンを変更すると前のシーンにあったオブジェクトは基本的に全て破棄されてしまいます

 シーンを跨いで変数を共有してみましょう。

​ staticを使ってゲームからリザルトに変数を引き継いでみましょう。GameTimerスクリプトを以下のように変更してみてください。赤い部分が変更箇所です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

 

public class GameTimer : MonoBehaviour
{
    static float m_second;   // 秒
    static int m_minute;     // 分

    // 分と秒を返す関数
    static public float GetSecond()
    {
        return m_second;
    }
    static public int GetMinute()
    {
        return m_minute;
    }

 

    void Start()
    {
        // 計測時間を初期化
       
m_second = 0.0f;
        m_minute = 0;
    }

 

    void Update()
    {
        // タイマー加算
        m_second += Time.deltaTime;
        if (m_second > 60.0f)
        {
            // 1分経過
            m_minute++;
            m_second -= 60.0f;
        }
    }
}

2

変更による
​エラーを修正

【プログラムの解説】

関数にstatic public をつけると、 クラス名.関数名 でどのクラスからも関数を参照できるようになります。

 注意しなければならないのが、staticにした変数はシーンを跨いでも持ち越される=そのままでは初期化されない ということです。初期化をしないとステージに再挑戦しても時間がリセットされずどんどん加算されていくことになってしまいます。Startに初期化を記述することでゲームが始まった時に毎回タイムを初期化するようにしています。

 この変更を行うとTimerUIスクリプトに関数をstaticに変更したことによるエラーが発生します。

 代わりに型名を使用してくださいと書いてある通り、変数ではなく型名を使うようにしましょう赤い部分のように修正してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

 

public class TimerUI : MonoBehaviour
{
    TextMeshProUGUI m_timerTMP;
    //public GameTimer Game_Timer;

 

    void Start()
    {
        m_timerT
MP= GetComponent<TextMeshProUGUI>();
    }

 

    void Update()
    {
        // 現在の時間を表示
        string timeString = "";
        
        timeString = GameTimer.GetMinute().ToString("00");
        timeString += ":";
        timeString += Mathf.Floor(GameTimer.GetSecond()).ToString("00");

        m_timerTMP.text = timeString;
    }
}

 

3

クリアタイムUIを
​更新

 後は同じようにリザルトでもタイムを取得、表示するだけです。どの方法を使っても構いませんが、教材では新しくResultTimerUIスクリプトを作成してアタッチしています​。

​ 参考にしたい方はResultTimerUIスクリプトを作成して以下のように入力してください。

using System.Collections.Generic;
using UnityEngine;
using TMPro;

 

public class ResultTimeUI : MonoBehaviour
{
    TextMeshProUGUI m_timerTMP;

 

    void Start()
    {
        m_timer
TMP= GetComponent<TextMeshProUGUI>();
    }

 

    void Update()
    {
        // 現在の時間を表示
        string timeString = "";

 

        timeString += "ClearTime ";
        timeString += GameTimer.GetMinute().ToString("00");
        timeString += ":";
        timeString += Mathf.Floor(GameTimer.GetSecond()).ToString("00");

        m_timerTMP.text = timeString;
    }

}

 ResultTimerUIスクリプトをリザルトシーンのクリアタイム用TextMeshProにアタッチしてください。

​ 実行してクリアタイムがリザルトに引き継がれていたらOKです。

 一通りの機能は実装できたのでこれで完成でもよいのですが、最後のLessonでは音やエフェクトを実装してゲームを装飾してみましょう。

 変数にstatic publicをつけると クラス名.変数名 でどのクラスからも変数を参照できるようになります。

​ 便利ですが、どこからでもアクセスできるということはどこから変更されるかわからないということでもあるので、使い方には注意しましょう。

Unity Tips!

まとめ

・UnityではタイトルやインゲームをScene(シーン)で分けて作り、切り替えることができる

 Build Settings内のScenes In Buildに切り替え先のシーンを含んでいないと切り替えられない

​・シーンを切り替えると切り替え前のシーンにあったオブジェクトは基本的に破棄される

・変数にstaticをつけることでシーンを跨いでも値が破棄されないようになる

​ ただし初期化は手動で行う必要があるので注意する

まとめ

評価テスト

評価テスト

河原電子ビジネス専門学校
​ゲームクリエイター科

bottom of page