(Unity)シーン間でスコアデータを引き継ぐ方法(static 静的メンバ/シングルトン)

(スコアを管理する基本スクリプト)

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

public class ScoreManager : MonoBehaviour
{
    public string nextScene;
    public TextMeshProUGUI scoreLabel;
    public int clearScore;

    // ★スコアデータを管理するフィールド
    private int score = 0;

    void Start()
    {
        scoreLabel.text = "Score:" + score;
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            score += 10;
            scoreLabel.text = "Score:" + score;

            if(score > clearScore)
            {
                SceneManager.LoadScene(nextScene);
            }
        }
    }
}

(実行結果)

  • シーンを遷移すると、スコアデータがリセットされて「0」に戻ってしまう。
  • その理由は、スコアデータが「各シーンの個々のオブジェクトで」管理されているため。
  • Unityは原則としてシーンを遷移すると、オブジェクトは破壊される。


(シーン間でスコアデータを引き継ぐ方法その1)
  • スコアデータを「静的フィールド(静的メンバ)」にして、「クラスで管理」する。
  • 複数のシーンで「同じスクリプトをオブジェクトに追加」すればスコアデータを引き継げるようになる。

 

(スクリプトの改良)

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

public class ScoreManager : MonoBehaviour
{
    public string nextScene;
    public TextMeshProUGUI scoreLabel;
    public int clearScore;

    // ★「static」を追加して、静的メンバにする。
    private static int score = 0;

    void Start()
    {
        scoreLabel.text = "Score:" + score;
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            score += 10;
            scoreLabel.text = "Score:" + score;

            if(score > clearScore)
            {
                SceneManager.LoadScene(nextScene);
            }
        }
    }
}

(実行結果)

  • シーンを遷移してもスコアデータが引き継がれていれば成功
  • ただし、この方法は、「同じスクリプト」を「シーンごとにオブジェクトに追加する必要がある」という点がめんどくさい場合がある。
  • この点を解消するやり方が次の「シングルトン」

(シーン間でスコアデータを引き継ぐ方法その2)
  • シングルトンとは、「実行時にそのクラスのインスタンスが必ず1つになるように設計」すること。
  • 要するに、「あるスクリプトを追加したオブジェクトが1つしか存在しない」ようにすること。
  • そして、このオブジェクトがシーンを遷移しても破壊されないようにすることで、スコアデータが引き継がれる。

(スクリプトの改良)

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

public class ScoreManager : MonoBehaviour
{
    // ★追加
    static public ScoreManager instance;

    public string nextScene;
    public TextMeshProUGUI scoreLabel;
    public int clearScore;

    // ★「static」を削除
    private int score = 0;

    // ★追加
    private void Awake()
    {
        if(!instance)
        {
            instance = this;

            // シーン遷移しても破壊されないようにする。
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    void Start()
    {
        scoreLabel.text = "Score:" + score;
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            score += 10;
            scoreLabel.text = "Score:" + score;

            if(score > clearScore)
            {
                SceneManager.LoadScene(nextScene);
            }
        }
    }
}