目次
- 環境
- 概要
- [SerializeFiled]について
- PropertyをInspectorに公開する方法
- class, structをInspectorに公開する方法
- まとめ
- おまけ Inspectorで上書きした値が保存される場所
環境
Unity 2019.3.13f1
概要
組み込み型、Property、struct/classの Inspectorへの公開方法をまとめた記事になります
Unityのシリアル化については下記のドキュメントに記載があります
スクリプトのシリアル化 - Unity マニュアル
C#の型情報についてのドキュメントはこちら
型 - C# プログラミング ガイド | Microsoft Docs
[SerializeFiled]について
主に変数をInspectorに公開するために使用することが多いです
public class ExampleBehaviour : MonoBehaviour { // 書き方は2通りあり、改行してもしなくてもよい [SerializeField] int ExampleValue = 10; [SerializeField] int Value = 10; }
public / private を書かなくてもよいのか、publicとの違い
先ずはpublic / privateを書かなくてもよいのかについてですが
C#のclassはアクセス修飾子がない場合に明示的にprivateになります
そのため以下の2つは同じ意味を持ちます
[SerializeField] int ExampleValue = 10; // どちらの書き方でも同じ意味をもつ [SerializeField] private int Value = 10;
次にpublicとの違いについて
public の場合[SerializeField]を付けなくてもInspectorに変数を公開できます
そこまでは同じです
ですが、アクセス修飾子が異なるので他のクラスから変更できてしまいます
[SerializeField] int ExampleValue = 10; public int Value = 10;
このクラス単体に限っては何の問題もありません
ただし、他のクラスから変更できてしまうため以下のような問題が発生します
先ずはExampleBehaviour にアクセスするためのクラスを用意します
public class TestBehaviour : MonoBehaviour { [SerializeField] ExampleBehaviour Example; void Start() { Example.Value = 100; } }
実行するとInspector上で"10"だったExampleValueが"100"に上書きされてしまいます
この書き方の場合には意図しない値の変更が行われる可能性があり
バグを生み出す原因となり得ます
Unityに限らずアクセス修飾子には気を付けましょう
PropertyをInspectorに公開する方法
Propertyは以下のようにSerializeFieldを付けてもInspectorに公開できません
[SerializeField]
int ExampleValue { get; set; }
解決方法として[field: ] を付与することでInspectorに公開することができます
[field: SerializeField]
int ExampleValue { get; set; }
backing field の表記になりパッと見では分かりにくくなってしまいます
(Propertyを公開していることを意図的に表現したい場合はこのままでよいですが)
解決策として以下のForumにある「RenameFieldAttribute」のようなclassを用意することで解決できます
https://forum.unity.com/threads/c-7-3-field-serializefield-support.573988/
public class ExampleBehaviour : MonoBehaviour { [field: SerializeField] [field: RenameField(nameof(ExampleProperty))] int ExampleProperty { get; set; } [field: SerializeField] [field: RenameField("RenameValue")] int Value { get; set; } }
class, structをInspectorに公開する方法
classもstructもそのままではInspectorに公開することができません
using UnityEngine; public class ExampleBehaviour : MonoBehaviour { public struct StructData { public int Value; public string Name; } [SerializeField] StructData structData; public class ClassData { [SerializeField] string Tag; } [SerializeField] ClassData classData; }
どちらの場合でもInspectorに公開する場合は[System.Serializable] を使用することでInspectorに公開できます
using UnityEngine; public class ExampleBehaviour : MonoBehaviour { [System.Serializable] public struct StructData { public int Value; public string Name; } [SerializeField] StructData structData; [System.Serializable] public class ClassData { [SerializeField] string Tag; } [SerializeField] ClassData classData; }
まとめ
ここまでに紹介してきた書き方をざざっとまとめました。
using System; using UnityEngine; public class ExampleBehaviour : MonoBehaviour { [SerializeField] int ExampleValue; [field: SerializeField] int PropertyValue { get; set; } // ※RenameFieldの拡張用のclassを記述した場合 [field: SerializeField] [field: RenameField("RenameProperty")] int RenameValue { get; set; } // struct, class どちらの場合でも[System.Serializable]で対応可能 // ここではusing System;を定義しているためSystemを省略 [Serializable] public class ClassData { public string Name; [SerializeField] string Tag; } [SerializeField] ClassData classData; }
おまけ Inspectorで上書きした値が保存される場所
Inspector上で書き換えた値はScene fileに紐付いて保存されています
例えば以下のように設定しておいた場合
scene.unity ファイルをエディターで開いてgrepすると
以下のように保存されていることが確認できます
MonoBehaviour: ... (省略) m_EditorClassIdentifier: structData: Value: 2000 Name: Enemy classData: Tag: Player
普段中身を見ることは少ないとは思いますが
デカいSceneを開かないでgrepして値を追いたい時など何かしら使うケースがあるかもしれません