目次
[SerializeFiled]について
主に変数をInspectorに公開するために使用することが多いです
public class ExampleBehaviour : MonoBehaviour
{
[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; }
[field: SerializeField]
[field: RenameField("RenameProperty")]
int RenameValue { get; set; }
[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して値を追いたい時など何かしら使うケースがあるかもしれません