Unity入門

【Unity】変数のスコープ・使い方 | 変数の共有、ローカル・メンバー・グローバル、public・private・static、SerializeField、シングルトン

Unityのスクリプトを書く際に、変数のスコープ(適用範囲)を理解することは非常に重要 です。

  • ローカル変数・メンバー変数・グローバル変数の違い
  • public・private・staticの使い分け
  • スクリプト間での変数の共有方法(public、static)
  • SerializeFieldの活用方法
  • シングルトンとは何か?

適切に変数を管理することで、コードの可読性が向上し、バグを減らすことができます。

この記事でわかること

  • ローカル変数・メンバー変数・グローバル変数の違いと使い方
  • 変数のスコープ(適用範囲)を理解し、バグを減らす
  • スクリプト間での変数の受け渡し方法(public、static)
  • SerializeFieldを使った変数の管理とpublicとの違い
  • シングルトンパターンを活用して、ゲーム全体のデータを統一的に管理する方法

変数のスコープ(適用範囲)・使い方

変数のスコープとは、その変数がどこでアクセスできるかを示す範囲のことです。スコープを適切に設定することで、コードの保守性が向上し、予期しないバグを防ぐことができます。

※ この他にも以下のサイトを参考にしてください。

スコープの種類

種類適用範囲用途
ローカル変数メソッド内のみ一時的なデータ
メンバー変数クラス内(private・public)オブジェクトごとのデータ保持
グローバル変数staticを付けた変数ゲーム全体でのデータ共有

ローカル変数とメンバー変数(グローバル変数)の違い

ローカル変数とメンバー変数では使用できる範囲(スコープ)が異なります。
このスクリプトを試していただくとわかりますが、score1は数値が増えるがscore2は呼ばれるたびに初期化されるため増えないですね。

using UnityEngine;

public class ScopeExample : MonoBehaviour
{
    public int score1; //メンバー変数

    void Start()
    {
        score1 = 1;
    }
    void Update()
    {
        CountUp();
    }
    //voidの手前に何も書いてない場合は「public」になる
    private void CountUp()
    {
        int score2 = 1; //ローカル変数

        score1 += score1 +1;
        score2 += score2 +1;

        Debug.Log("score1:" + score1);  //Consoleにデバッグ結果を出力する
        Debug.Log("score2:" + score2);  //Consoleにデバッグ結果を出力する
    }
}

Unityで使われるpublicとprivateの違い

修飾子Inspectorで変更可能他のスクリプトからアクセス可能
public
SerializeField private
private

SerializeFieldを活用した変数管理

Unityでは、SerializeFieldを使うと、private変数でもInspectorから変更可能になります

SerializeFieldを使うとprivate変数でもInspectorで編集可能
外部スクリプトから直接変更できないため、安全性が向上

public class Player : MonoBehaviour
{
    [SerializeField] private int health = 100; // Inspector で表示される

    void Start()
    {
        Debug.Log("初期体力: " + health);
    }
}

クラス間の変数の共有

public変数のクラス間の受け渡し

public class GameManager
{
    public int highScore = 0; // すべてのスクリプトからアクセス可能
}

public class Player : MonoBehaviour
{
    public GameManager gameManager; //Inspectorでアタッチが必要
    void Start()
    {
        gameManager.highScore = 100;
        Debug.Log("ハイスコア: " + gameManager.highScore);
    }
}

static変数のクラス間の受け渡し

public class GameManager
{
    public static int highScore = 0; // すべてのスクリプトからアクセス可能
}

public class Player : MonoBehaviour
{
    void Start()
    {
        GameManager.highScore = 100;
        Debug.Log("ハイスコア: " + GameManager.highScore);
    }
}

シングルトンとは?

シングルトンとは、ゲーム全体で唯一のインスタンスを保証するデザインパターン です。通常、ゲームの進行状況や設定情報を管理するために使用されます。

シングルトンの実装例

GameManager.Instanceでどこからでもアクセス可能
シーンが変わっても DontDestroyOnLoad()でデータを保持


※ static変数を使用していたとしてもアタッチしたオブジェクトがシーン間でDestroyされたら変数の値は消えます。(誤情報が多いので誤解しないように!)

public class GameManager : MonoBehaviour
{
  //static変数
    public static GameManager Instance { get; private set; }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

シングルトンのメリットとデメリット

メリットデメリット
データの一元管理が可能依存関係が強くなりすぎると、テストが難しくなる
グローバル変数より安全にデータ共有ができる乱用すると、設計が複雑になる可能性がある
オブジェクトの重複を防ぐことで、メモリの無駄を減らせる

まとめ

ローカル変数 → メソッド内だけで使える、一時的なデータ保存に最適
メンバー変数(public、private) → オブジェクトごとのデータ管理に最適
グローバル変数(static) → すべてのスクリプトで共有可能、ただし制御が必要
SerializeFieldを使うと、Inspectorで編集できるがスクリプト外部からは変更不可
シングルトンを使えば、ゲーム全体のデータを安全に管理可能