★Yuki Yamashita

(2024年4月6日)

<ランキングシーンの作成>

「TimeSave」スクリプトの改良

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

// ★改良
// コードを見比べて不要なコードを削除する!
public class TimeSave : MonoBehaviour
{
    private string filePath;
    public Text[] recordLabels;
    private List playRecordTimes = new List();

    void Start()
    {
        filePath = Application.persistentDataPath + "/TimeData.json";

        LoadData();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha0))
        {
            ClearData();
        }
    }

    public void SaveData(float amount)
    {
        playRecordTimes.Add(amount);

        string json = JsonUtility.ToJson(new TimeData(playRecordTimes));

        File.WriteAllText(filePath, json);
    }

    void LoadData()
    {
        if (File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            TimeData timeData = JsonUtility.FromJson(json);
            playRecordTimes = timeData.saveRecordTimes;
        }
    }

    // ★改良
    // 先頭に「public」を追加する。
    public void SortAndDisplayRecords()
    {
        playRecordTimes.Sort((a, b) => b.CompareTo(a));

        for (int i = 0; i < recordLabels.Length; i++)
        {
            if (i < playRecordTimes.Count)
            {
                recordLabels[i].text = playRecordTimes[i].ToString("n3");
            }
            else
            {
                recordLabels[i].text = "00:00";
            }
        }
    }

    void ClearData()
    {
        playRecordTimes.Clear();

        File.WriteAllText(filePath, "");

        for (int i = 0; i < recordLabels.Length; i++)
        {
            recordLabels[i].text = "00:00";
        }
    }
}

[Serializable]
public class TimeData
{
    public List saveRecordTimes;

    public TimeData(List times)
    {
        saveRecordTimes = times;
    }
}

・「PlayerHP」スクリプトの改良

・ゲームオーバーシーンに遷移するようにする。

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

public class PlayerHP : MonoBehaviour
{
    public TimeSave timeSave;
    public TimeCounter timeCounter;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("ENEMY"))
        {
            Destroy(other.gameObject);

            float time = timeCounter.elapsedTime;
            timeSave.SaveData(time);

            // ★改良
            SceneManager.LoadScene("GameOver");
        }
    }
}

・新規にシーンの作成

・名前を「GameOver」に変更

・このシーンに「ランキング表」を作成(MAINシーンにある「TimeCanvas」をプレハブ化して活用すると便利!)

・MAINシーンに戻るために「リスタートボタン」を作成する。

・新規にC#スクリプトを作成

・名前を「Restart」に変更

・下記のコードを書いて、ボタンを動作させる設定を行う。

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

public class Restart : MonoBehaviour
{
    public void OnRestartButtonClicked()
    {
        SceneManager.LoadScene("MAIN");
    }
}

<GameOverシーンの設定>

・新規にCreate Emptyオブジェクトの作成

・名前を「TimeSave」に変更

・これに「TimeSave」スクリプトを追加

・空欄に「Record_Label」を設定

・新規にC#スクリプトを作成

・名前を「DisplayRanking」に変更

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

public class DisplayRanking : MonoBehaviour
{
    public TimeSave timeSave;

    void Start()
    {
        timeSave.SortAndDisplayRecords();
    }
}

・新規にCreate Emptyオブジェクトの作成

・名前を「DisplayRanking」に変更

・これに「DisplayRanking」スクリプトを追加

・空欄に「TimaSave」オブジェクトをドラッグ&ドロップ

<Mainシーンの設定>

・MAINシーンではランキングを表示しないので、「TimeCanvas」の中で不要なものを削除して整理する。

・「TimeSave」オブジェクトを選択して

・「Record Labels」を「0」にする。

 


(2024年3月30日)

<ランキングデータの保存&表示>

・新規にC#スクリプトの作成

・名前を「TimeSave」に変更

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// ★追加
using UnityEngine.UI;
using System;
using System.IO;

public class TimeSave : MonoBehaviour
{
    private string filePath;

    public Text[] recordLabels;
    private List<float> playRecordTimes = new List<float>();

    public GameObject recordPanel;

    void Start()
    {
        // ファイルまでのパスの取得
        filePath = Application.persistentDataPath + "/TimeData.json";

        // データのロード
        LoadData();
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Alpha1))
        {
            recordPanel.SetActive(true);

            SortAndDisplayRecords();
        }

        if(Input.GetKeyDown(KeyCode.Alpha2))
        {
            recordPanel.SetActive(false);
        }

        if(Input.GetKeyDown(KeyCode.Alpha0))
        {
            ClearData();
        }
    }

    // ①データの保存
    public void SaveData(float amount)
    {
        // リストにデータを追加する
        playRecordTimes.Add(amount);

        // データをJSON形式の文字列に変換する
        string json = JsonUtility.ToJson(new TimeData(playRecordTimes));

        // 変換したJSON形式の文字列を指定したファイルに書き込む(ファイルはパスで指定)
        File.WriteAllText(filePath, json);
    }

    // ②データの読み込み
    void LoadData()
    {
        // 指定されたファイルパスにファイルが存在するかを確認する。
        if (File.Exists(filePath))
        {
            // ファイルからJSON形式の文字列を読み込む(取得する)
            string json = File.ReadAllText(filePath);

            // JSON形式の文字列を元のデータ構造に戻す(デシリアライズする)
            TimeData timeData = JsonUtility.FromJson<TimeData>(json);

            // 保存されたデータを活用する。
            playRecordTimes = timeData.saveRecordTimes;
        }
    }

    // ③タイム順に記録をソートして表示
    void SortAndDisplayRecords()
    {
        // ソート(降順)
        playRecordTimes.Sort((a, b) => b.CompareTo(a));

        // ソート後に表示
        for (int i = 0; i < recordLabels.Length; i++)
        {
            // 記録の数だけ表示する
            if (i < playRecordTimes.Count)
            {
                recordLabels[i].text = playRecordTimes[i].ToString("n3");
            }
            else
            {
                // 記録がない場合には「00:00」を表示する。
                recordLabels[i].text = "00:00";
            }
        }
    }

    // ④データのクリア
    void ClearData()
    {
        // リストのクリア
        playRecordTimes.Clear();

        // 保存されたファイル内のデータのクリア(空の文字列で上書きする)
        File.WriteAllText(filePath, "");

        // 表示ラベルのクリア
        for (int i = 0; i < recordLabels.Length; i++)
        {
            recordLabels[i].text = "00:00";
        }
    }
}

[Serializable]
public class TimeData
{
    public List<float> saveRecordTimes;

    // ★コンストラクタ
    // 初期値の設定
    // クラス名と同じ名前の「メソッド」
    public TimeData(List<float> times)
    {
        saveRecordTimes = times;
    }
}

「TimeCounter」スクリプトの改良

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

public class TimeCounter : MonoBehaviour
{
    public Text timeLabel;

    // ★改良
    public float elapsedTime { get; set; }

    // ★追加
    private void Start()
    {
        elapsedTime = 0;
    }

    private void Update()
    {
        elapsedTime += Time.deltaTime;

        // ★改良
        timeLabel.text = elapsedTime.ToString("n3");

        //int m = (int)elapsedTime / 60;
        //int s = (int)elapsedTime % 60;
        //int cs = (int)(elapsedTime * 100) % 60;

        //timeLabel.text = string.Format("{0:00}:{1:00}:{2:00}",m,s,cs);
    }
}

「PlayerHP」スクリプトの改良

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

public class PlayerHP : MonoBehaviour
{
    // ★追加
    public TimeSave timeSave;
    public TimeCounter timeCounter;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("ENEMY"))
        {
            Destroy(other.gameObject);

            // ★追加
            float time = timeCounter.elapsedTime;
            timeSave.SaveData(time);

            SceneManager.LoadScene("MAIN");
        }
    }
}

 


(2024年3月30日)

<ゲームオーバーで時間停止&ボタンクリックでリスタート>

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

public class PlayerHP : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("ENEMY"))
        {
            Destroy(other.gameObject);

            // ★追加
            Time.timeScale = 0;
        }
    }

    // ★追加
    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.T))
        {
            Time.timeScale = 1;
            SceneManager.LoadScene("MAIN");
        }
    }
}