Unity 6でプロパティはインスペクタに表示される? ― [field: SerializeField]と2つの書き方

広告

C#を学んでからUnityに入ると、「変数はプロパティにしましょう」と教わったのに、プロパティにした途端インスペクタから項目が消えてしまい、戸惑うことがあります。

この記事では、2026年9月時点の最新版であるUnity 6.6(6000.6系)で、C#のプロパティがインスペクタに表示されるのかどうかを、公式ドキュメントに沿って整理します。

結論:プロパティそのものは表示されない

Unity 6.6でも、C#のプロパティそのものはインスペクタに表示されません。

Unityのシリアライズ(値の保存)の仕組みは、クラスのフィールドを直接対象にしています。プロパティは対象外です。インスペクタに表示されるのは「シリアライズされたフィールド」なので、次のようなプロパティは表示されません。

using UnityEngine;

public class Player : MonoBehaviour
{
    // フィールド:インスペクタに表示される
    public int attack = 10;

    // プロパティ:インスペクタに表示されない
    public int Hp { get; set; } = 100;
}

ただし、プロパティの「中身」を保存しているフィールド(バッキングフィールド)をシリアライズすれば、インスペクタで値を設定できます。方法は2つあります。

方法1:自動実装プロパティに[field: SerializeField]を付ける

{ get; set; } と書く自動実装プロパティでは、コンパイラが見えないバッキングフィールドを自動で作ります。field: を付けて属性を書くと、そのバッキングフィールドに属性を付けられます。

using UnityEngine;

public class Player : MonoBehaviour
{
    [field: SerializeField]
    public int Hp { get; private set; } = 100;
}

これでインスペクタに「Hp」という項目が表示され、値を設定できるようになります。

private set と組み合わせるのがポイントです。

  • インスペクタからは値を編集できる
  • ほかのスクリプトからは読み取りだけできる(勝手に書き換えられない)

「インスペクタで初期値を決めたいが、ほかのクラスからは変更させたくない」という、Unityでよくある要望を1行で書けます。詳しい使い方は Unityのプロパティをもっとスッキリ書く![field: SerializeField]の使い方 でも解説しています。

方法2:バッキングフィールドを自分で書く

昔からある書き方です。[SerializeField] を付けたprivateフィールドを用意し、プロパティから読み書きします。

using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField, Range(0, 999)]
    private int hp = 100;

    public int Hp
    {
        get => hp;
        private set => hp = Mathf.Clamp(value, 0, 999);
    }
}

コードは長くなりますが、次のような利点があります。

  • [Range] などの属性をフィールドに素直に付けられる
  • フィールド名を自分で決めるので、後述する「名前変更で値が消える」問題が起きにくい

2つの方法の比較

方法1:[field: SerializeField]方法2:自分でフィールドを書く
コードの長さ短い(1行)長い
インスペクタでの表示名プロパティ名(Hp)フィールド名(hpが「Hp」と表示される)
setterの処理使えない(自動実装のため)書けるが、インスペクタからの変更では呼ばれない
名前変更への強さ弱い(内部名が変わる)強い
向いている場面単純な設定値値の制限や複雑な処理が必要なとき

注意点1:インスペクタで変更してもsetterは呼ばれない

方法2でsetterに Mathf.Clamp を書きましたが、インスペクタで値を変更したときは、このsetterは通りません。インスペクタが書き換えるのはフィールドそのものだからです。

そのため、インスペクタで 5000 と入力すると、フィールドにはそのまま 5000 が入ってしまいます。インスペクタからの入力も制限したい場合は、次のどちらかを使います。

  • フィールドに [Range(0, 999)] などの属性を付ける(上のコード例のように)
  • OnValidate() で値をチェックする
// インスペクタで値が変更されたときにエディタから呼ばれる
private void OnValidate()
{
    hp = Mathf.Clamp(hp, 0, 999);
}

注意点2:名前を変えると設定した値が消えることがある

方法1で作られるバッキングフィールドの本当の名前は、<Hp>k__BackingField のような特殊な名前です。そのため、プロパティ名を Hp から Health に変えると内部の名前も変わり、インスペクタで設定済みの値が初期値に戻ってしまいます。

同じことは、publicフィールドを自動実装プロパティに書き換えたときにも起こります。値を引き継ぎたいときは [FormerlySerializedAs] に以前の名前を指定します。

using UnityEngine;
using UnityEngine.Serialization;

public class Player : MonoBehaviour
{
    // 以前は public int hp; というフィールドだった場合
    [field: SerializeField, FormerlySerializedAs("hp")]
    public int Hp { get; private set; } = 100;
}

プロパティ名を変える場合は、以前の内部名 "<Hp>k__BackingField" を指定する必要があります。名前を頻繁に変える可能性があるなら、方法2のほうが安全です。

バッキングフィールドの仕組みそのものは、C# オートプロパティの裏側 ― コンパイラが生成するバッキングフィールドを覗いてみよう で詳しく紹介しています。

まとめ

  1. インスペクタに表示されるのはフィールドだけ。Unity 6.6でもプロパティそのものは表示されない
  2. 自動実装プロパティなら [field: SerializeField] を付けるとインスペクタで設定できる
  3. private set と組み合わせると「インスペクタで設定、外部からは読み取りのみ」が簡単に書ける
  4. インスペクタからの変更はsetterを通らないので、値の制限は [Range] や OnValidate() で行う
  5. 名前を変えると値が消えることがあるので、[FormerlySerializedAs] で引き継ぐ

シリアライズの基本をもう少し広く知りたい方は、Unityにおけるシリアライズと[SerializeField]の活用・プロパティのシリアライズ対策 もあわせて読んでみてください。

参考

訪問数 2 回, 今日の訪問数 2回

広告

C#,Unity,Unity6

Posted by hidepon