LoginSignup
7
3

More than 5 years have passed since last update.

Unityでシリアライズ名を指定する機能が欲しい

Posted at

 ゲームエンジン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.

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3