ゲームエンジンUnityにおいて、コンポーネントのpublicまたはUnityEngine.SerializeField
なフィールドのシリアライズは、そのフィールドの名前でシリアライズが行われます。
ところで、シリアライズにフィールド名以外を指定することができる機能が欲しいよね、というお話です。
UnityのバージョンはUnity 2017.2で検証しています。
Unityでのシリアライズ
こんなクラスがあって、
using UnityEngine;
using System;
[Serializable]
public class Enemy {
[SerializeField] int _hp;
[SerializeField] string _name;
public int Hp { get {return _hp; }}
public string Name { get {return _name; }}
}
こんな風に使います。
using UnityEngine;
public class Example : MonoBehaviour {
[SerializeField] Enemy _enemy;
}
そしてシーン上にGameObjectを作って、Exampleコンポートを付与します。
シーンファイル(*.unity、YAML形式)では、Exampleクラスのenemyフィールドはこんな感じでシリアライズされます。
_enemy:
_hp: 10
_name: "slime"
このようにUnityにおいて、シリアライズはフィールド名で行われます。
カプセル化されているフィールド名が変わるとき
本来C#においてprivateなフィールドはそのクラス内部で隠蔽されるべきものです。そして、フィールド名はいつでも気軽に変更可能なものなはずです。
けれどUnityにおいて、UnityEninge.SerializeField
がついているprivateなフィールドはシリアライズ名で使われているので、フィールド名の変更は慎重に行わないといけません。
もしフィールド名を変えると、せっかく設定した(シリアライズされている)値を捨てて再設定しないといけないです。
次のコードは、privateなフィールドに_
というプレフィックスをつけるルールのものです。
using UnityEngine;
using System;
[Serializable]
public class Enemy {
[SerializeField] int _hp;
[SerializeField] string _name;
public int Hp { get {return _hp; }}
public string Name { get {return _name; }}
}
ルールが変わって、_
というプレフィックスをつけなくなりました。
using UnityEngine;
using UnityEngine.Serialization;
using System;
[Serializable]
public class Enemy {
[SerializeField] int hp;
[SerializeField] string name;
public int Hp { get {return hp; }}
public string Name { get {return name; }}
}
これをしてしまうと、せっかくシリアライズした_hp
や_name
の値がなくなってしまい、再設定しないといけません。
これは、フィールド名を変えるときに、UnityEngine.Serialization.FormerlySerializedAs属性をつければ、値がなくなることを防ぐことができます。
using UnityEngine;
using UnityEngine.Serialization;
using System;
[Serializable]
public class Enemy {
[FormerlySerializedAs("_hp")]
[SerializeField]
int hp;
[FormerlySerializedAs("_name")]
[SerializeField]
string name;
public int Hp { get {return hp; }}
public string Name { get {return name; }}
}
確かにフィールド名が変わったときにFormerlySerializedAs
で問題は解決できるけれど、初めからシリアライズする名前をフィールド名に指定できてもいいと思います。
シリアライズ名指定機能、欲しいよね
フィールドを、フィールド名でシリアライズするだけでなく、明示的にシリアライズ名を指定できる機能が欲しいと思っています。
例えば、こんな感じのUnityEngine.Serialization.SerializedAs
using UnityEngine;
using UnityEngine.Serialization;
using System;
[Serializable]
public class Enemy {
[SerializedAs("hp")]
[SerializeField]
int _hp;
[FormerlySerializedAs("name")]
[SerializeField]
string _name;
public int Hp { get {return _hp; }}
public string Name { get {return _name; }}
}
もしくは、こんな感じでSerializeField
に機能を足してもいいと思います。
using UnityEngine;
using System;
[Serializable]
public class Enemy {
[SerializeField("hp")]
int _hp;
[SerializeField("name")]
string _name;
public int Hp { get {return _hp; }}
public string Name { get {return _name; }}
}
この機能はすべてのUnityユーザーが使うものではないけれど、ライブラリの開発者の中には、これで幸せになる人はいると思います。
関連: Vector2Intの互換ライブラリが作りたかった話!
Unity Feedbackに投稿したので賛同できる人は、Voteしてね!
「FEATURE THAT SPECIFIES SERIALIZED NAME NOT WITH FIELD NAME.」