基本:privateとpublic
変数の宣言時に「private」と「public」どちらのアクセス修飾子をつけるかによって、インスペクターでの見え方や外部クラスから参照できるかどうかが変わってきます。
アクセス修飾子を省略した場合は「private」と同じ扱いになります。
例えば、以下のようにprivateをつけた変数「a」、アクセス修飾子を省略した変数「b」、publicをつけた変数「c」があったとします。
public class InspectorTest : MonoBehaviour
{
private int a;
int b; // 省略した場合は「private」と同じ扱い
public int c;
}
この場合、インスペクターにはpublicで宣言した変数「c」のみが表示されます。
また、この変数を外部から参照しようとした場合は、publicで宣言した変数「c」のみが参照可能になります。
public class AccessTest : MonoBehaviour
{
void Update()
{
InspectorTest inspectorTest = new InspectorTest();
// private:他クラスからは参照できない(エラーになる)
//Debug.Log(inspectorTest.a);
//Debug.Log(inspectorTest.b);
// public:他クラスからも参照できる
Debug.Log(inspectorTest.c);
}
}
属性を付与する
スクリプト内のクラスや変数に属性を付与することで特殊な挙動を設定することができます。
C#では[○○○]のように角括弧で囲って記述します。
今回は、SerializeField、HideInInspector、NonSerializedの3つの属性を使用します。
privateな変数をインスペクターに表示する
「private変数だけどインスペクターにも表示したい」という場合はSerializeFieldを使用します。
public class InspectorTest : MonoBehaviour
{
[SerializeField] private int d;
[SerializeField] int e;
}
SerializeFieldをつけて宣言すると、private変数でもインスペクターに表示されるようになります。
通常のprivate変数と同じく、外部からの参照はできません。
public class AccessTest : MonoBehaviour
{
void Update()
{
InspectorTest inspectorTest = new InspectorTest();
// SerializeField:他クラスからは参照できない(エラーになる)
//Debug.Log(inspectorTest.d);
//Debug.Log(inspectorTest.e);
}
}
publicな変数をインスペクターに表示させない
「public変数だけどインスペクターには表示したくない」という場合はHideInInspectorまたはNonSerializedを使用します。
public class InspectorTest : MonoBehaviour
{
[HideInInspector] public int f;
[NonSerialized] public int g;
}
HideInInspectorまたはNonSerializedをつけて宣言すると、public変数でもインスペクターに表示されなくなります。
通常のpublic変数と同じく、外部からも参照が可能です。
public class AccessTest : MonoBehaviour
{
void Update()
{
InspectorTest inspectorTest = new InspectorTest();
// HideInInspector:他クラスからも参照できる
Debug.Log(inspectorTest.f);
// NonSerialized:他クラスからも参照できる
Debug.Log(inspectorTest.g);
}
}
HideInInspectorとNonSerializedの違い
どちらを使用してもインスペクターには表示されなくなりますが、実は挙動が少し異なります。
- HideInInspector:シリアライズするけどインスペクターには表示しない
- NonSerialized:シリアライズしない
シリアライズについての詳細な説明は省きますが、publicまたはSerializeField属性がついているとシリアライズされる(=インスペクターから操作が可能になる)と考えてください。
そして、HideInInspectorはインスペクターの表示を隠しているだけなので、HideInInspectorをつける前にインスペクター上で値を変更していた場合はその値が残ってしまいます。
例えば、以下のようなコードがあったとします。
public class InspectorTest : MonoBehaviour
{
public int h = 10;
public int i = 100;
void Start()
{
Debug.Log("h:" + h + ", i:" + i);
}
}
このまま実行した場合、出力されるのは宣言時の値、つまり「h=10、i=100」になります。
ここで試しにインスペクターでh=50、i=500を入力して実行すると、コンソールには変更後の値である「h=50、i=500」が出力されます。
ではここで、変数hにHideInInspector、変数iにNonSerializedをつけてみます。
public class InspectorTest : MonoBehaviour
{
[HideInInspector] public int h = 10;
[NonSerialized] public int i = 100;
void Start()
{
Debug.Log("h:" + h + ", i:" + i);
}
}
インスペクターには表示されなくなるので値の変更はできません。
このまま実行してみると、変数hは先ほどインスペクターで入力した値(50)のままになっていて、変数iはスクリプトで初期化した値(100)になりました。
HideInInspectorはあくまでインスペクター上の表示を隠しただけなので、入力値はまだ内部に残った状態になっています。
このように意図しない値が残るのはバグの原因になってしまいます。
そのため、単純にインスペクターに表示したくないだけの場合はNonSerializedを使用することをオススメします。
さいごに
インスペクターで変数を表示・非表示にする方法をまとめると、以下になります。
インスペクターで表示
- public
- [SerializeField] private
インスペクターで非表示
- private
- [HideInInspector] public
- [NonSerialized] public
外部から変数を参照できるかどうかは、その変数が「private」か「public」かによって変わります。
また、Unity(C#)で使用できる属性は今回紹介した3つ以外にもたくさんあります。
インスペクターを拡張するもの、コンポーネントに関連するものなど色々あるので、気になる方はぜひ調べてみてください。
コメント