Unityでスクリプトを記述しているときに、
Sceneを切り替えても前のシーンでの変数を引き継ぎたい。
スクリプトを複数に分けて書くときに、
他のスクリプトの変数を現在のスクリプトで取得したい。
このように変数を共有・受け渡す場合には、
変数の前にアクセス修飾子を付ける必要があります。
Unity(C#)の文法では、intやfloatなどのC言語やPythonと同様に使用される変数の型の他に、
[SerializeField]やpublic、privateなどを使用し、これらをアクセス修飾子と呼びます。
アクセス修飾子はUnity(C#)だけではなく、JavaやC++などにもpublicやprivateなどがあります。
アクセス修飾子を使わずにUnityを使うことはできないです。
本記事では、Unityでよく使う[SerializeField]やpublic、privateについて理解しつつ、Unityでゲーム開発をする際にいつ使うのか、使い分けを紹介します。
- Unityで変数を共有したい。
- アクセス修飾子について知りたい。
アクセス修飾子
アクセス修飾子は、オブジェクト指向のプログラミング言語(Java・C++・C#・Python・Rudy・Swift etc.)において、クラスのメンバー(変数やメソッド)へのアクセス範囲を制御するために使用されるキーワードです。
参考サイト:「アクセス修飾子 – C# プログラミング ガイド」
言語によって使えるアクセス修飾子は違う
Pythonは、オブジェクト指向の言語ですが、前述したようにアクセス修飾子がありません。
オブジェクト指向であっても言語によって使用できるアクセス修飾子は異なります。
以下に、各言語で使用できるアクセス修飾子をまとめました。
言語 | private | public | protected | default | internal | protected internal | fileprivate | open |
Java | ○ | ○ | ○ | ○ | × | × | × | × |
C++ | ○ | ○ | ○ | × | × | × | × | × |
C#(Unity) | ○ | ○ | ○ | × | ○ | ○ | × | × |
Python | × | × | × | × | × | × | × | × |
Rudy | × | × | × | × | × | × | × | × |
Swift | ○ | ○ | × | × | ○ | × | ○ | ○ |
表に示したように、PythonとRudyはアクセス修飾子を使用しません。
Unityは、C#をもとにして開発し、使用できるアクセス修飾子は5つあります。
一般的に使用されるのは、PublicとPrivate、Protectedです。
個人的な意見として、PublicとPrivateを押さえれば、大丈夫です。
[SerializeField]は、実際にはアクセス修飾子ではありません。
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 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に移動するときはロードをしないといけません。
ゲームはシーン切り替え(遷移)をすることが主流です。
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” にシーンを切り替えます。
スクリプトを実行すると、次のようになります。
シーンを切り替えるとaは加算した数字は初期化されますが、bはシーンを変えても保持されます。
UdemyでUnityを学習
Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。
- 【Unity C# ゲーム開発超入門】7つのミニゲームを作っておぼえる!UnityとC#講座
Unityで頻出の機能を実際のゲーム作りで学習。
何か作りたい、今後の開発で役立てたい初心者におすすめ
- 【Unity C# ゲーム開発初心者レベルアップ】7つのトランプゲームを作っておぼえる!UnityとC#講座
トランプやボードゲーム作りに特化している講座。
テーブルゲームを作りたい人におすすめ。
- 【全行程を網羅!最初に学びたい総合学習】Unityワールド制作講座
Unityワールド制作の全工程を学習できる講座。
RPGを作りたい人におすすめ。
- Unity ゲーム開発:インディーゲームクリエイターが教える C#の基礎からゲームリリースまで【スタジオしまづ】
C#の文法やApp StoreとGoogle Playへゲームをリリース方法を解説。
ゲームを出品したい人におすすめ。
「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」はアクセスの制限をせずに、どのプログラムからでも参照、変更が可能です。
「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ウィンドウに変数とオブジェクトが表示されます。
[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は、他のクラスから参照、変更することができます。