【Unity】C#で使えるプロパティとは?メンバ変数を安全に制御するための仕組み

C#で使えるプロパティ Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「C#のプロパティってなに?」

「プロパティはどんな時に使うの?」

というお悩みの方に向けた内容となっています。

Unityのプログラミング言語であるC#では、プロパティという仕組みがあります。

このプロパティとは、外部のクラスからメンバ変数にアクセスするための機能で、メンバ変数に値を代入するための「set」と、値を取得するための「get」という2つのアクセサをまとめています。

プロパティを使うことで、外部のクラスからメンバ変数を直接変更したり、誤った値を代入するのを防ぐために使われます。

そこで、このページでは、Unityで使われているC#のプロパティの機能について、どんな仕組みなのか、また使い方や書き方などをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

C#のプロパティとは?

C#のプロパティがどんな仕組みなのか、またプロパティを使う目的について紹介していきます。

アクセサを簡略化するための仕組み

プロパティとは、アクセサをより簡潔にまとめた仕組みのことを指しています。

そもそもアクセサというのは、privateのアクセス修飾子を付けて宣言したメンバ変数に、外部のクラスからアクセスするためのメソッドのことを指しています。

なお、アクセス修飾子については、以下の記事で詳しく解説していますので、参考にしてみてください。

例えば、以下のスクリプトを見てみましょう。

public class NumSample
{
    private int num;    // 他のクラスからアクセスできない変数

    // メンバ変数に値を代入するアクセサ
    public void SetNum(int num)
    {
        this.num = num;
    }

    // メンバ変数の値を取得するアクセサ
    public int GetNum()
    {
        return this.num;
    }
}

3行目で宣言している変数numには、アクセス修飾子で「private」を付けているため、他のクラスからは直接アクセスすることができなくなっています。

そこで、6行目でSetNumというメソッド、また12行目でGetNumというメソッドを作って、外部のクラスからアクセスできるようにpublic修飾子を付けておきます。

このSetNumGetNumといったメソッドのことをアクセサと呼びます。

そして、以下のように別のクラスから、このアクセサを使って変数numにアクセスしてみます。

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Start()
    {
        NumSample numSample = new NumSample();
        numSample.SetNum(100);  // アクセサを介してnumに100を代入
        Debug.Log("numの値は" + numSample.GetNum());   // アクセサを介してnumの値を取得する
    }
}

他のクラスからアクセスする際は、8行目でSetNumのアクセサを使ってメンバ変数のnumに値を代入、9行目のDebug.Logの中でGetNumのアクセサを使ってnumの値を取得することができます。

そして、このアクセサを使った仕組みをより簡略化することができるのがプロパティの機能となっています。

プロパティの書き方

プロパティを書く際は、以下のような形で書いていきます。

public プロパティの型 プロパティ名
{
	set
	{
		変数 = value;
	}
	get
	{
		return 変数;
	}
}

プロパティ名は、最初の文字だけ大文字で書くのが基本です。

そして、「set」「get」がそれぞれアクセサの部分になっていて、

  • set ⇒ メンバ変数に値を代入する処理
  • get ⇒ メンバ変数の値を取得する処理

を書いていくことになります。

例えば、先ほどの章で説明したスクリプトでプロパティを使うと、以下のような記述になります。

public class NumSample
{
    private int num;    // 他のクラスからアクセスできない変数

    public int Num
    {
        // メンバ変数に値を代入するアクセサ
        set
        {
            num = value;
        }
        // メンバ変数の値を取得するアクセサ
        get
        {
            return num;
        }
    }
}

5行目から16行目がNumというプロパティの部分で、setの中では代入する値をvalueで指定して変数に値を代入し、getの中ではreturnを使って変数の値を返す処理を作っています。

他のクラスからアクセスする場合は、

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Start()
    {
        NumSample numSample = new NumSample();
        numSample.Num = 100;  // プロパティから100を代入
        Debug.Log("numの値は" + numSample.Num);   // プロパティから値を取得する
    }
}

8行目のようにプロパティに値を代入することで、setに書かれている「変数に値を代入する処理」が行われます。

また、9行目のようにプロパティの値を取得することで、getに書かれている「メンバ変数の値を返す処理」が行われます。

プロパティを使う目的

ここまでプロパティの仕組みや使い方を紹介していきましたが、プロパティを使う目的として、外部のクラスからメンバ変数を直接いじれないようにして、メンバ変数に変な値が入らないように監視する、という目的があります。

例えば、ゲーム内の体力を表す変数hpを作り、このhpの最大値を100、最小値を0としたいとします。

まずは、外部のクラスからこのメンバ変数を直接いじれてしまう場合を考えてみます。

public class HpManager
{
    public int hp;    // 他のクラスからアクセスできる変数
}

3行目で変数hpを宣言していますが、public修飾子を付けているため、この変数は外部のクラスからでもアクセスすることが出来てしまいます。

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Start()
    {
        HpManager hpManager = new HpManager();
        hpManager.hp = 250; // 直接メンバ変数に代入できてしまう
        Debug.Log("HPの値は" + hpManager.hp);
    }
}

そのため、上記のように「250」などの想定していない値でも入れることができるようになってしまいます。

このように誤って想定していない値が入るのを防ぐために、プロパティの仕組みが使われています。

今度は、プロパティでメンバ変数へのアクセスを制御したスクリプトを作ってみます。

using UnityEngine;

public class HpManager
{
    private int hp;    // 他のクラスからアクセスできない変数

    // プロパティを作成
    public int Hp
    {
        set
        {
            hp = Mathf.Clamp(value, 0, 100);    // 0から100までの間の値を代入する
        }
        get
        {
            return hp;
        }
    }
}

12行目のメンバ変数に値を代入する処理を行うsetの部分で、代入する値が0から100までに必ず収まるように、Mathf.Clampメソッドを使って制御した値を、メンバ変数hpに代入しています。

Mathf.Clampメソッドは、以下のように引数で指定した範囲の中で、数値を返してくれるメソッドです。

Mathf.Clamp(float value, float min, float max);

value:判定したい数値
min:最小の数値
max:最大の数値

今回の場合、このMathf.Clampでvalueが100以上であれば最大の100、valueが0以下であれば最小の0をメンバ変数hpに代入してくれるようになります。

実際に外部のクラスからプロパティを使ってみると、

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Start()
    {
        HpManager hpManager = new HpManager();
        hpManager.Hp = 250; // 「250」は最大値を超えているので100が代入される
        Debug.Log("HPの値は" + hpManager.Hp);
        hpManager.Hp -= 999;    // 「999」を引くと最小値を下回るので0が代入される
        Debug.Log("HPの値は" + hpManager.Hp);
    }
}

8行目で250を代入していますが、hpの最大値を超えているため、メンバ変数には最大の100が代入されています。

また、10行目で999を引いてしまっても、hpの最小値より低いため、メンバ変数には最小の0が代入されています。

このように、アクセサを使ったプロパティの仕組みを作ることで、メンバ変数に誤った値が代入されてしまうことを防ぐことができます。

まとめ

このページでは、Unityで使うC#の機能であるプロパティについて、どんな仕組みなのか、使い方や目的までをまとめていきましたが、いかがでしたでしょうか?

C#のプロパティとは、外部のクラスからメンバ変数にアクセスするための「get」「set」のアクセサをまとめているものになっています。

プロパティを使うことで、外部のクラスからメンバ変数に直接アクセスできないようになり、おかしな値が変数に入らないようにチェックすることができます。

ゲーム内の体力やスコアなど、おかしな値を入れたくない場合にプロパティの仕組みを使ってみましょう。

最後までお読みいただきまして、ありがとうございました!

コメント