【Unity】シーンをまたぐ変数の共有するアクセス修飾子を紹介

当サイトで紹介する商品・サービス等の外部リンクは、アフィリエイト広告を含む場合があります。
スポンサーリンク

Unityでスクリプトを記述しているときに、
Sceneを切り替えても前のシーンでの変数を引き継ぎたい

スクリプトを複数に分けて書くときに、
他のスクリプトの変数を現在のスクリプトで取得したい

このように変数を共有・受け渡す場合には、
変数の前にアクセス修飾子を付ける必要があります。

Unity(C#)の文法では、intfloatなどのC言語やPythonと同様に使用される変数の型の他に、
[SerializeField]publicprivateなどを使用し、これらをアクセス修飾子と呼びます。

アクセス修飾子はUnity(C#)だけではなく、JavaやC++などにもpublicやprivateなどがあります。
アクセス修飾子を使わずにUnityを使うことはできないです。

本記事では、Unityでよく使う[SerializeField]やpublic、privateについて理解しつつ、Unityでゲーム開発をする際にいつ使うのか、使い分けを紹介します。

本記事は次の人におすすめ
  • Unityで変数を共有したい。
  • アクセス修飾子について知りたい。
Udemyで学習する
スポンサーリンク

アクセス修飾子

アクセス修飾子は、オブジェクト指向のプログラミング言語(Java・C++・C#・Python・Rudy・Swift etc.)において、クラスのメンバー(変数やメソッド)へのアクセス範囲を制御するために使用されるキーワードです。

参考サイト:「アクセス修飾子 – C# プログラミング ガイド

言語によって使えるアクセス修飾子は違う

Pythonは、オブジェクト指向の言語ですが、前述したようにアクセス修飾子がありません
オブジェクト指向であっても言語によって使用できるアクセス修飾子は異なります。

以下に、各言語で使用できるアクセス修飾子をまとめました。

言語privatepublicprotecteddefaultinternalprotected internalfileprivateopen
Java××××
C++×××××
C#(Unity)×××
Python××××××××
Rudy××××××××
Swift×××

表に示したように、PythonとRudyはアクセス修飾子を使用しません

Unityは、C#をもとにして開発し、使用できるアクセス修飾子は5つあります。
一般的に使用されるのは、PublicとPrivate、Protectedです。

著者の体験談
著者の体験談

個人的な意見として、PublicとPrivateを押さえれば、大丈夫です。

[SerializeField]は、実際にはアクセス修飾子ではありません。

private

privateは、変数やメソッドが同じクラス内からのみアクセス可能な修飾子です。

クラスの内部でのみ利用されるので、
他のスクリプトはprivateを使用しているデータや処理を干渉することができません

privateのメリット
  • 外部からの不正なアクセスや意図しない変更を防止。
  • データの整合性やセキュリティを保護が可能。

以下にコードの例を紹介します。

public class Sample1 : MonoBehaviour
{
    private int pr_myInt; // プライベートな変数

    private void Start()
    {
        pr_myInt = 10;
    }
}

このスクリプトはプライベートな変数を宣言しています。
この変数は、同じクラス内のメソッドからのみアクセスできます。

次に、プライベートなメソッドの使用例を紹介します。

public class Sample2 : MonoBehaviour
{
    void Start()
    {
        pr_Fn();
    }

    private void pr_Fn()
    {
        // プライベートな処理
    }
}

「pr_Fn」というプライベートなメソッドを定義しています。

Startメソッド内でpr_Fnメソッドを呼び出すことができますが、
他のクラスから直接呼び出すことはできません。

※Unityでスクリプトには、「void Start」が作成されています。
実は、Startメソッドもprivateな関数です。

public

publicは、変数やメソッドがどのクラスや外部からでもアクセス可能である修飾子です。

publicのメリット
  • クラスの再利用性や拡張性が向上し、柔軟性のある設計が可能。
  • 共同作業やオープンソースプロジェクトの管理が容易。
  • 他のコードとの連携を確認ができて、バグの発見と修正が容易。

以下にコードの例を紹介します。

public class Sample3 : MonoBehaviour
{
    public int Pb_myInt;// パブリックな変数

    void Start()
    {
        Pb_myInt = 10;
    }
}

このスクリプトはパブリックな変数を宣言しています。

次に、パブリックなメソッドの使用例を紹介します。

public class MyClass
{
    public void pu_Fn()
    {
        // パブリックな処理
    }
}

このpu_Fn()は同じスクリプト内で処理することも可能で、別のスクリプトから扱うこともできます。

static publicで別のスクリプトの変数を使用する

最近のゲームはオープンワールドといわれるエリアの移動制限がないものが多くなっています。
通常は、エリア1があり、エリア2に移動するときはロードをしないといけません。
ゲームはシーン切り替え(遷移)をすることが主流です。

Sceneを切り替えるときはロードが必要

Unityでは、シーンを切り替えると画面を切り替えると変数は保持されずに初期化されてしまいます。
初期化されるということは、エリアを移動したら、プレイヤーのHPが元に戻る、敵へのダメージが蓄積されていないなどの現象を指します。

したがって、Unityではシーンをまたぐときに変数を共有して保持する必要があります。
シーン間で変数が保持するにはstatic(静的な)を紹介します。

以下のソースコードは、ボタンを押すと数字が加算されるソースコードです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UIを適用
using UnityEngine.SceneManagement; // シーン切り替えに必要

public class Test : MonoBehaviour
{
    public int a = 0;
    public static int b = 0;
    public Button plusBtn; // ボタンの参照

    void Start()
    {
        Debug.Log(SceneManager.GetActiveScene().name+ "@a:::" + a);
        Debug.Log(SceneManager.GetActiveScene().name+ "@b:::" + b);
    }

    public void Plus()//UIボタンを押すと加算される
    {
        a++;
        b++;
        Debug.Log(SceneManager.GetActiveScene().name + "@a:::" + a);
        Debug.Log(SceneManager.GetActiveScene().name + "@b:::" + b);
    }

    public void Change()
    {
        if (SceneManager.GetActiveScene().name == "SceneA")
        {
            SceneManager.LoadScene("SceneB");
        }
        else
        {
            SceneManager.LoadScene("SceneA");
        }
    }
}

a ,bはint型変数で、bは静的な(static)を宣言し、クラスの全インスタンス間で共有されます。

plusBtnはUIボタンで押すと、Plus()によってa,bを1ずつ加算(インクリーメント)します。
UIを使用するので、UnityEngine.UIを入れる必要があります。

スコアのカウントアップについて紹介しています。

Change()によって、現在地が “SceneA” であれば “SceneB” 。
それ以外(スクリプトでは、”SceneB”を意味する)の場合は “SceneA” にシーンを切り替えます。

シーン切り替えできない

SceneManager.LoadScene()でシーン切り替えをしようとしても、エラー文が表示されます。

原因は、作成したシーンを表示設定していないためです。
設定は、FileからBuild Settingsの項目を選択します。

Scene設定をしないと、エラー文が憑依される。

ウィンドウの「Add Open Scenes」を押すと、現在作成されたシーンが表示されます。

スクリプトを実行すると、次のようになります。

ボタンを押すと数字が加算される実行

シーンを切り替えるとaは加算した数字は初期化されますが、bはシーンを変えても保持されます。

発展1

staticは、シーン遷移のときに変数を引き継ぐだけではなく、
他にも別のスクリプトで定義した変数を呼び出すことができます。

しかし、静的メンバーは依存関係を増やし、複雑なシングルトンパターンはテストや保守性の観点から問題が生じることがあります。

staticを使わず、他のスクリプトから関数を呼ぶ方法
発展2

シーン遷移で、staticを使えば変数を保持することができますが、
UIボタンやUIテキストなどゲームオブジェクト(GameObject)が残ってしまったり、消えてしまったりなど保持、初期化する時にはDontDestroyOnLoadを使用しなければいけません。

DontDestroyOnLoadの解説をしています。

UdemyでUnityを学習

Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。

\Unityの学習から収益化の方法はこちらから!/



「public」・「private」の違い

アクセス修飾子「private」・「public」の使い方を紹介してきました。

ここからは、Unity上でどのように使うか紹介します。

using UnityEngine;

public class pu_pr : MonoBehaviour
{
    // 変数定義
    public int pu_Int;       // パブリックな整数型変数
    private int pr_Int;      // プライベートな整数型変数
    public float pu_Float;   // パブリックな浮動小数点型変数
    private float pr_Float;  // プライベートな浮動小数点型変数
    public string pu_String; // パブリックな文字列型変数
    private string pr_String;// プライベートな文字列型変数

    // メソッド
    public void method1()
    {
        // 処理
    }

    private void method2()
    {
        // 処理
    }
}

本スクリプトをアタッチすると、 public型変数はInspectorウィンドウに表示されます。
一方で、private型変数は非表示です。

publicのみInspectorウィンドウに表示

要するに、「public」はアクセスの制限をせずに、どのプログラムからでも参照、変更が可能です。
「private」は記述されたスクリプト以外からのアクセスをできないように制限します。

メソッドはInspectorウィンドウに表示されません。
メソッドは、クラスのインスタンスから呼び出すことができますが、
privateであるmethod2()は同じクラス内からのみ呼び出すことができます。

SerializeField

SerializeFieldは、publicと同じように変数やプロパティをUnityのInspectorウィンドウに表示可能にするために使用されます。

具体的には、SerializeField属性を変数やプロパティの前に記述することで、
その変数やプロパティがUnityのインスペクター上で編集可能になります。
これにより、ゲームオブジェクトやコンポーネントのプロパティを直接設定することができます。

以下にSerializeFieldを使用したコードを示します。

using UnityEngine;

public class Serialize : MonoBehaviour
{
    [SerializeField]
    private int se_Int;

    [SerializeField]
    private float se_Float;

    [SerializeField]
    private GameObject se_GameObject;

    // ...
}

プライベートな変数ですが、シリアライズフィールドとしてマークしているため、
スクリプトをアタッチすると、Inspectorウィンドウに変数とオブジェクトが表示されます。

シリアライズフィールドとしてマークしたプライベートな変数はInspectorウィンドウに表示される。

[SerializeField]とpublicの相違点

[SerializeField]とpublicの違いがないように見えますが、
実際は、2つの間には大きな違いがあります。

前述したserializeFieldのソースコードにて、3つの変数すべてアクセス修飾子がprivateです。
一方で、serializeFieldで定義した変数はpublicのようにinspectorウィンドウ内で編集ができます。

要するに、SerializeField属性はシリアライズされた変数をインスペクター上で編集可能にします。

あえて例えるならば、「much」、「many」、「a lot of」の3つの関係のようにといえるでしょう。
※3つの語句は、肯定文では使わない、どんな文にでも使えるなどそれぞれの表現があるので、混乱する場合は無視してください。

語句可算名詞不可算名詞
much×
many×
a lot of

まとめると、serializeFiledとpublicの違いは、他のクラスからでも参照できる変数の宣言はpublic。
インスペクター上に表示し他のクラスからは参照できない変数の宣言は[SerializeField]を使うと考えれば大丈夫です。

まとめ

[SerializeField]は、インスペクタ―(Inspector)からアクセスするとき変数を定義するときに使います。

publicとprivateはアクセス修飾子と呼称される一種で、アクセス修飾子とはクラスやメソッド、変数がどこから参照や変更しているのか決定するものです。

「public」はアクセスの制限がなく、どのプログラムやクラスからでも参照、変更が可能です。
「private」は記述されたスクリプト内のみでアクセスができます。

[SerializeField]とpublicはInspectorウィンドウに変数を表示することは同じです。

しかし、[SerializeField]は、他のクラスから参照、変更することはできません。
publicは、他のクラスから参照、変更することができます。

Udemyで学習する

この記事を書いた人

プロフィール

アリッシア

                 

大学4年間で何か胸を張れるスキルを身に着けたくて当サイト運営を始めました。
現在、大学院に進学するか就職するか迷いながら勉強しています。
詳しいプロフィールはこちら

Contact icon

contact

X icon

X

Instagram icon

Instagram

Note icon

Note

スポンサーリンク
Unity
フォローする
タイトルとURLをコピーしました