2024プログラミング:Unityのプログラミング4

スタート画面の作成

スタートシーンを作成します。ProjectウィンドウのScenesフォルダを右クリックしてCreateからSceneを選択します。新規Sceneが作成されるので、StartSceneと名前を付けます。

作成したStartSceneをダブルクリックしてSceneビューの表示を切り替えます。StartSceneに切り替わったら、Hierarchyウィンドウの+ボタンを押してUIからCanvasを選択します。

更にHierarchyウィンドウの+ボタンを押してUIからPanelを選択します。PanelがCanvasの子になったことを確認します。HierarchyウィンドウでPanelを選択し、InspectorウィンドウのRect TransformコンポーネントのScaleでサイズをX、Y、Zそれぞれに2を入力します。PanelのInspectorウィンドウからImageコンポーネントを選択し、Colorの横にある四角のエリアをクリックするとColorウィンドウが開くので任意の色を選択し決定します。

Hierarchyウィンドウの+ボタンを押してUIからText-TextMeshProを選択します。Text(TMP)のInspectorウィンドウで各種設定をします。Rect TransformコンポーネントのPos Xに10、Pos Yに30、Pos Zに0、Widthに200、Heightに40と入力します。TextコンポーネントのTextにゲームタイトルをアルファベットで入力します。Font Sizeに30と入力します。Colorの横にある四角のエリアをクリックするとColorウィンドウが開くので任意の色を選択し決定します。

Hierarchyウィンドウの+ボタンを押してUIからButtonを選択します。ButtonのInspectorウィンドウのRect TransformコンポーネントのPos Xに0、Pos Yに-70、Pos Zに0と入力します。ButtonにUIのTextが子として設定されているので、Buttonの子のTextのInspectorウィンドウのTextコンポーネントにSTARTと入力します。

スクリプトを作成します。Hierarchyウィンドウの+ボタンを押してCreate Emptyを選択して空のゲームオブジェクトを作成し、StartSceneControllerという名称にします。Scriptsフォルダーにスクリプトを作成し、StartSceneControllerという名称にして、StartSceneControllerゲームオブジェクトにアタッチします。
StartSceneControllerゲームオブジェクトのInspectorウィンドウでStartSceneControllerスクリプトがアタッチできているか確認しておきます。
StartSceneControllerスクリプトに以下のコードを記述します。

StartSceneController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;//追加

public class StartSceneController : MonoBehaviour
{
     public void OnGameStart()
     {
           SceneManager.LoadScene("GameScene");
     }
}

STARTボタンの設定をします。ButtonのInspectorウィンドウを表示し、Buttonコンポーネントを表示します。
On Click()の+ボタンをクリックしてから◉をクリックし、Select Objectウィンドウを表示し検索欄に、StartSceneControllerと入力しSceneタブを選び、StartSceneControllerをダブルクリックします。次にメソッドの呼び出しを設定します。No Functionから、StartSceneControllerを選択し、OnGameStart( )をクリックします。これで、STARTボタンを押すと、StartSceneController.csスクリプト内のOnGameStartメソッドが呼び出されるように設定できました。

OnGameStartメソッドの処理でシーン StartSceneから、シーン GameSceneをロードして実行できるように設定します。Unityの画面上部のメニューからFileを選択し、Build Settingsをクリックします。
Build Settingsウィンドウが表示されるので、ProjectウィンドウのStartSceneをScenes in Buildにドラッグアンドドロップします。
Scenes in BuildにScenes/StartSceneが追加されたのを確認したら、次にGameSceneをドラッグアンドドロップします。
Scenes/StartSceneの下にScenes/GameSceneが追加できているのを確認したら、Build Settingsウィンドウを閉じます。

HierarchyウィンドウにStartSceneが表示されている状態でゲームを実行するとスタート画面からゲームが開始されます。STARTボタンを押してゲームが開始されるか確認してみましょう。

リザルト画面の作成

ProjectウィンドウのScenesフォルダを右クリックしてCreateからSceneを選択します。新規Sceneが作成されるので、ResultSceneと名前を付けます。
作成したResultSceneをダブルクリックしてSceneビューの表示を切り替えます。

ResultSceneに切り替わったら、Hierarchyウィンドウの+ボタンを押してUIからCanvasを選択します。更にHierarchyウィンドウの+ボタンを押してUIからPanelを選択します。PanelがCanvasの子になったことを確認します。HierarchyウィンドウでPanelを選択し、InspectorウィンドウのRect TransformコンポーネントのScaleでサイズをX、Y、Zそれぞれに2を入力します。PanelのInspectorウィンドウからImageコンポーネントを選択し、Colorの横にある四角のエリアをクリックするとColorウィンドウが開くので任意の色を選択し決定します。Hierarchyウィンドウの+ボタンを押してUIからText-TextMeshProを選択します。Hierarchyウィンドウに追加されたText(TMP)を複製しText(TMP)を3つ作成します。Text(TMP)の名称は、Text、Text(TMP)(1)、Text(TMP)(2)になります。

Text(TMP)のInspectorウィンドウで設定します。PosX 0、PosY 80、PosZ 0、Width 230、Height 40と入力します。TextコンポーネントのTextエリアに適切な文書を記載します。(GOAL!!など)ColorエリアでTextに任意の色を設定しておきます。

Text(TMP)(1)のInspectorウィンドウで設定します。PosX -5、PosY 20、PosZ 0、Width 160、Height 30と入力します。TextコンポーネントのTextエリアにTOTAL SCOREと記載します。ColorエリアでTextに任意の色を設定しておきます。

Text(TMP)(2)をScoreTextと名称変更します。ScoreTextのInspectorウィンドウで設定します。PosX 130、PosY 20、PosZ 0、Width 160、Height 30と入力します。TextコンポーネントのTextエリアに0と記載します。ColorエリアでTextに任意の色を設定しておきます。

Hierarchyウィンドウの+ボタンを押してUIからButtonを選択します。ButtonのInspectorウィンドウのRect TransformコンポーネントのPos Xに0、Pos Yに-70、Pos Zに0と入力します。ButtonにUIのTextが子として設定されているので、Buttonの子のTextのInspectorウィンドウのTextコンポーネントにRESTARTと入力します。

スクリプトを作成します。Hierarchyウィンドウの+ボタンを押してCreate Emptyを選択して空のゲームオブジェクトを作成し、ResultSceneControllerという名称にします。Scriptsフォルダーにスクリプトを作成し、ResultSceneControllerという名称にして、ResultSceneControllerゲームオブジェクトにアタッチします。
ResultSceneControllerゲームオブジェクトのInspectorウィンドウでResultSceneControllerスクリプトがアタッチできているか確認しておきます。

GameSceneControllerスクリプトの変数宣言部分を確認します。

GameSceneController.cs (一部抜粋)

public class GameSceneController : MonoBehaviour 
{ 
     public static int score = 0; //変数のグローバル化
     private Text scoreText;

ResultSceneControllerスクリプトに以下のコードを記述します。

ResultSceneController.cs

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

public class ResultSceneController : MonoBehaviour
{
    private TextMeshProUGUI scoreText;

    void Start()
    {
        GameObject textObject = GameObject.Find("ScoreText");
        scoreText = textObject.GetComponent<TextMeshProUGUI>();
        scoreText.text = GameSceneController.score.ToString(); ;
    }

    public void OnGameStart()
    {
        SceneManager.LoadScene("GameScene");
    }
}

RESTARTボタンの設定をします。ButtonのInspectorウィンドウを表示し、Buttonコンポーネントを表示します。
On Click()の+ボタンをクリックしてから◉をクリックし、Select Objectウィンドウを表示し検索欄に、ResultSceneControllerと入力しSceneタブを選び、ResultSceneControllerをダブルクリックします。次にメソッドの呼び出しを設定します。No Functionから、ResultSceneControllerを選択し、OnGameStart( )をクリックします。これで、RESTARTボタンを押すと、ResultSceneController.csスクリプト内のOnGameStartメソッドが呼び出されるように設定できました。

OnGameStartメソッドの処理でシーン ResultSceneから、シーン GameSceneをロードして実行できるように設定します。Unityの画面上部のメニューからFileを選択し、Build Settingsをクリックします。
Build Settingsウィンドウが表示されるので、ProjectウィンドウのResultSceneをScenes in Buildにドラッグアンドドロップします。
Scenes/StartSceneの下にScenes/GameScene、その下にScenes/ResultSceneが追加できているのを確認したら、Build Settingsウィンドウを閉じます。

HierarchyウィンドウにResultSceneが表示されている状態でゲームを実行するとリザルト画面からゲームが開始されます。RESTARTボタンを押してゲームが再開されるか確認してみましょう。

ゴール処理の作成

ProjectウィンドウのScenesフォルダにあるGameSceneをダブルクリックしてHierarchyウィンドウの表示をGameSceneに切り替えます。Roadゲームオブジェクトの1つを複製(Duplicate)し適切な場所に配置し、Goalという名称に変更します。
ProjectウィンドウのScriptsフォルダにGoalスクリプトを作成し、Goalゲームオブジェクトにアタッチしておきます。

各スクリプトに必要なコードを追記し変更します。

Controller.cs

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

public class Controller : MonoBehaviour
{
   private float speed = 3f;
   private float verticalInput = 0f;
   private Rigidbody CharacterRigidbody;
   private bool isStop = false;

   void Start()
   {
      CharacterRigidbody = GetComponent<Rigidbody>();
      isStop = false;
   }

   void Update()
   {
      if (isStop)
      {
         return;
      }

      if (transform.position.y < 0.5)
      {
         isStop = true;
         GameObject gameSceneController = GameObject.Find("GameSceneController");
         GameSceneController script = gameSceneController.GetComponent<GameSceneController>();
         script.OnFailed();
      }
      else
      {
         verticalInput = Input.GetAxis("Vertical");

         if (Input.GetKey("right"))
         {
            transform.Rotate(0, 10, 0);
         }
         else if (Input.GetKey("left"))
        {
            transform.Rotate(0, -10, 0);
        }
      }
   }

   void FixedUpdate()
   {
      if (isStop)
      {
         return;
      }

      if (CharacterRigidbody.velocity.sqrMagnitude < 5f)
      {
          Vector3 CharacterForward = CharacterRigidbody.transform.forward;
          Vector3 moveVector = speed * (CharacterForward * verticalInput);
          moveVector.y = 0;
          CharacterRigidbody.AddForce(moveVector, ForceMode.Impulse);
      }
   }
  //追記ここから=====>
   public void OnStop()
   {
      isStop = true;
   }
  //======>ここまで
}

GameSceneController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class GameSceneController : MonoBehaviour
{
   public static int score = 0;
   private Text scoreText;

   void Start()
   {
      GameObject gameScoreText = GameObject.Find("ScoreText");
      scoreText = gameScoreText.GetComponent<Text>();
      score = 0;
   }

   public void OnFailed()
   {
      Invoke("OnLoadGameScene", 1.5f);
   }

   private void OnLoadGameScene()
   {
      SceneManager.LoadScene("GameScene");
   }

   public void AddScore(int num)
   {
      score += num;
      scoreText.text = score.ToString();
   }
   //追記=====>
   public void OnGoal()
   {
      GameObject Character = GameObject.Find("Character");
      Controller script = Character.GetComponent<Controller>();
      script.OnStop();
      Invoke("OnLoadResultScene", 1.5f);
   }

   private void OnLoadResultScene()
   {
      SceneManager.LoadScene("ResultScene");
   }
   //=====>ここまで
}

Goal.cs

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

public class Goal : MonoBehaviour
{
   void OnCollisionEnter(Collision collision)
   {
      GameObject controller = GameObject.Find("GameSceneController");
      GameSceneController script = controller.GetComponent<GameSceneController>();
      script.OnGoal();
   }
}

ゲームキャラクターを動かしてゴールさせてみましょう。リザルト画面にシーンが遷移したら成功です。

RESTARTボタンを押すとGameSceneに戻ることができます。