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

　ゲームエンジンUnityにおいて、コンポーネントのpublicまたは`UnityEngine.SerializeField`なフィールドのシリアライズは、そのフィールドの名前でシリアライズが行われます。

　ところで、シリアライズにフィールド名以外を指定することができる機能が欲しいよね、というお話です。

　UnityのバージョンはUnity 2017.2で検証しています。

# Unityでのシリアライズ

　こんなクラスがあって、

```csharp
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; }}
}
```

　こんな風に使います。

```csharp
using UnityEngine;

public class Example : MonoBehaviour {
  [SerializeField] Enemy _enemy;
}
```

　そしてシーン上にGameObjectを作って、Exampleコンポートを付与します。

　シーンファイル(*.unity、YAML形式)では、Exampleクラスのenemyフィールドはこんな感じでシリアライズされます。

```yaml
  _enemy: 
    _hp: 10
    _name: "slime"
```

　このようにUnityにおいて、シリアライズはフィールド名で行われます。

# カプセル化されているフィールド名が変わるとき

　本来C#においてprivateなフィールドはそのクラス内部で隠蔽されるべきものです。そして、フィールド名はいつでも気軽に変更可能なものなはずです。

　けれどUnityにおいて、`UnityEninge.SerializeField`がついているprivateなフィールドはシリアライズ名で使われているので、フィールド名の変更は慎重に行わないといけません。

　もしフィールド名を変えると、せっかく設定した（シリアライズされている）値を捨てて再設定しないといけないです。

　次のコードは、privateなフィールドに`_`というプレフィックスをつけるルールのものです。

```csharp
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; }}
}
```

ルールが変わって、`_`というプレフィックスをつけなくなりました。


```csharp
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属性をつければ、値がなくなることを防ぐことができます。

```csharp
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`

```csharp
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`に機能を足してもいいと思います。

```csharp
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の互換ライブラリが作りたかった話！](https://speakerdeck.com/ryotamurohoshi/vector2intfalsehu-huan-raiburarigazuo-ritakatutahua)

　Unity Feedbackに投稿したので賛同できる人は、Voteしてね！

「[FEATURE THAT SPECIFIES SERIALIZED NAME NOT WITH FIELD NAME.](https://feedback.unity3d.com/suggestions/feature-that-specifies-serialized-name-not-with-field-name)」