アクセス修飾子
C#を初めとしてプログラミング言語には、アクセス出来る範囲を指定するアクセス修飾子
というものがあります。
publicとprivate
他にもありますが、public
とprivate
の違いについて考えてみます。
public class Player
{
public int _level = 1;
private int _hp = 10;
}
public | どこからでもアクセス出来る。アクセスが制限されない |
private | class,structの中からしかアクセス出来ない |
Unityにおいて、MonoBehaviour、ScriptableObjectを継承したクラスだと以下の要素が追加されます
using UnityEngine;
public class Player : MonoBehaviour
{
public int _level = 1;
public int _hp = 10;
private int _mp = 5;
}
public | インスペクタ上に表示され、値を編集できる |
private | インスタンス上には表示されない |
public
とした場合、シリアライズ対象になるためインスペクタ上に表示され、
編集した内容もシーンやプレハブに保存されます。
public変数で起きうる問題
個人で開発している場合は余り気にならないかもしれませんが、以下の様な問題が起きます。
どこからでも書き換えられる
public変数の場合クラスの外からでも書き換えられるため、
実際にどこから変更されたのか突き止めるのが困難になります。
自分でコードを書いたんだからそんなことしない、と思うかもしれませんが、
1ヶ月後の自分は他人です。
値を設定できると誤解される
複数人で開発していて、プログラマ以外がUnityEditor上で作業することがある場合、
インスペクタ上に公開されている値は初期値として使用できる
ものとして誤解される可能性があります。
「ここに初期値を設定しておいたのに、ゲームを始めると全然違う値になるんだけど!?」
「初期値0の筈がいつの間にか100って入力されてて、ゲーム開始早々ステージクリアになる!?」
といったトラブルがあるかもしれません。
SerializeField属性
UnityではSerializeField
という属性を使用できます。
using UnityEngine;
public class Player : MonoBehaviour
{
public int _level = 1;
[SerializeField] private int _hp = 10;
private int _mp = 5;
}
public | どこからでもアクセス出来る。インスペクタ上に表示される。 |
[SerializeField] priavte | class,structの中からしかアクセス出来ない。インスペクタ上に表示される。 |
private | class,structの中からしかアクセス出来ない。インスペクタ上に表示されない。 |
SerializeField
を指定した場合、シリアライズ対象となりインスペクタ上に表示されるようになります。
ですが、private
変数であるためクラス外から参照されることも変更されることもありません。
何かおかしな値が入っていても影響範囲はクラス内に絞られるので原因を調べやすいです。
public
変数の使用をやめ、[SerializeField] private
な変数を使用するよう徹底すると
余計な変数をインスペクタ上に公開しなくて済み、
またインスペクタ上で設定できる値がゲーム中に使用される
というルールで統一されるので、
おかしな値を設定されて問題が起きるということもなくなるでしょう。
private変数にアクセスしたい
値を取得したい場合
プロパティでgetter
のみ設定して、クラス外から値を参照できるようにします。
// 変数
private int _mp = 5;
// プロパティ
public int Mp
{
get
{
return _mp;
}
}
この場合読み取りのみなので、外部から勝手に書き換えることは出来ません。
以下の様に書くことも出来ます。
public int Mp => _mp;
値を変更したい
プロパティでsetter
を設定することでクラス外から書き換えられるようにする事も出来ます。
// 変数
private int _mp = 5;
// プロパティ
public int Mp
{
get
{
return _mp;
}
set
{
_mp = value;
}
}
もしくはpublicメソッド
を用意するかです。
個人的にはこちらをおすすめします。
public void SetMp(int mp)
{
_mp = mp;
}
public
変数を直接書き換える場合と違い、代入される前に上限下限をチェックすることも出来ますね。
public void SetMp(int mp)
{
_mp = Math.Clamp(mp, 0, 100);
}
public変数をやめよう
というわけでpublic
変数を使うのはおすすめしません。
- [SerializeField]
- プロパティ
- メソッド
を使うようにしましょう。
Unityの入門書やサンプルコードでよくpublic
変数が使われている印象ですが、
ある程度Unityの開発になれて新しいプロジェクトを立ち上げたら、
public
変数について考えてみてください。