1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】シーン間の値受け渡しにグローバル変数を使うのはやめよう

Last updated at Posted at 2024-06-14

グローバル変数による値渡し

Unityでシーン間で値の受け渡しをしたいこと、多いですよね。
例えばゲームシーンからリザルトシーンにスコア情報を渡したりなどが挙げられます。

その時に最も簡便かつ危険な方法が、グローバル変数を用いる手法です。

public static class GlobalVariables
{
    public static int score;
}

public class GameView : MonoBehaviour
{
    private void GoToResult()
    {
        GlobalVariables.score = 100;
        SceneManager.LoadScene("Result");
    }
}

public class ResultView : MonoBehaviour
{
    private void Start()
    {
        Debug.Log($"Score: {GlobalVariables.score}");
    }
}

このような書き方をすると、scoreはどこからでも参照・代入できるようになり、
ゲーム規模が大きく・人数が増えると管理し切れなくなり、とても危険です

ここでいうグローバル変数はどこからでもアクセスできるものであり、シングルトンやPlayerPrefsも同様です。
これらを値渡しに使うのは避けましょう。

シーン間の依存による値渡し

そこで次に考えるのが、下記のようにシーン間で直接値を渡す方法です。

public class GameView : MonoBehaviour
{
    private async void GoToResult()
    {
        await SceneManager.LoadSceneAsync("Result");
        var result = GameObject.FindObjectOfType<ResultView>();
        result.Initialize(100);
    }
}

public class ResultView : MonoBehaviour
{
    public void Initialize(int score)
    {
        Debug.Log($"Score: {score}");
    }
}

これはグローバル変数による授受と比較すると、かなりマシではあります。

ただし、この手のシーンオブジェクト(GameView, ResultView)は肥大化するものであり、GameViewがResultViewそのものに依存するのには依然として危険性があります。
また、シーン同士が相互参照して結局スパゲティになるリスクもあります。

シーンマネージャーとパラメータに依存した値渡し

上記を踏まえて、直接シーンに依存するのは避けたいです。

ではどうするかというと、シーンマネージャーという、シーン遷移と値渡しを行うクラスを用意して、そこに代わりに行ってもらいます。

public static class GameSceneManager
{
    public static async void LoadScene(string sceneName, object parameter)
    {
        await SceneManager.LoadSceneAsync(sceneName);
        var scene = GameObject.FindObjectOfType<SceneBase>();
        scene.Initialize(parameter);
    }
}

public abstract class SceneBase : MonoBehaviour
{
    public virtual void Initialize(object param) { }
}

public class GameView : SceneBase
{
    private async void GoToResult()
    {
        GameSceneManager.LoadScene("Result", 100);
    }
}

public class ResultView : SceneBase
{
    public override void Initialize(object param)
    {
        Debug.Log($"Score: {param as int}");
    }
}

このような実装にすることで、GameViewはResultViewのパラメータの形だけ知っておけば良いので、
疎結合な状態で安全にパラメータを渡すことが可能になります。

実際にシーンマネージャーを設計する際には、ジェネリクスを用いたりなど、より安全な構成にするのが良いでしょう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?