- Unityの標準的な機能としてPlayerPrefsというロード・セーブの機能がある
- これは整数や文字列などの基本的な型だけを受け付ける
- 標準的な機能としてJSONUtilityもある
- なので複雑な型はJSONUtility.ToJson()で文字列にしてPlayerPrefsで保存するのがよい
- しかしJsonUtilには罠がある
- UnityのJSONUtilityでListをシリアライズしても{}になる
- JSONとしてValidなのでFromUtility<List>で読み書きできてしまうが、中身が空なのでヌル参照エラー
- そもそもListどころかArrayもシリアライズできない
- 仕様です
- 直接Arrayをシリアライズすることはできないが、Arrayをフィールドに持つクラスのインスタンスはシリアライズできる
- Vector3[]をフィールドに持つクラスFooのJsonUtil.ToJsonは成功するが、それをJsonUtil.FromJsonしようとするとコンパイルエラー。Fooへの変換方法をコンパイラが理解できないため。
- あらかじめ作っておいたFooのインスタンスfooに対してJsonUtil.FromJsonOverwrite(json, foo)なら成功する
- 情報を仲介するプロキシクラスを作って、プロパティのgetter/setterで情報を集めたり分配したりすればよいかなと思ったが、シリアライズ時にgetter/setterが呼ばれないようなので明示的に呼ぶことにした
cs
public class SlidePositionProxy : MonoBehaviour {
public void BeforeGet()
{
Debug.Log("BeforeGet");
var slides = GameObject.Find("MotherMonolith").GetComponent<MakeSlides>().slides;
Debug.Log(slides.Count);
var positions = new Vector3[slides.Count];
for (int i = 0; i < slides.Count; i++)
{
positions[i] = slides[i].transform.position;
}
Positions = positions;
}
public void AfterSet()
{
Debug.Log("AfterSet");
var slides = GameObject.Find("MotherMonolith").GetComponent<MakeSlides>().slides;
for (int i = 0; i < slides.Count; i++)
{
slides[i].transform.position = Positions[i];
}
}
[SerializeField]
public Vector3[] Positions;
}