前提・実現したいこと
Unity/C#によるゲーム開発をしています。
データのセーブ・ロードをJSONシリアライズ/デシリアライズにより実現しようと考えていたところ、
下記の問題に思い当たりました。
発生している問題・エラーメッセージ
「シリアライズによりオブジェクト参照関係が失われ、デシリアライズ時には複数のインスタンスが生成されてしまう」
例えばRPGで考えますと、キャラクターを管理するCharacterクラスのインスタンスと、
パーティーを管理するList<Character>のインスタンスがあるとします。
また、キャラクタはA, B, Cの3人。パーティーは1つだけで、キャラクタA,Bが所属している(Listに含まれている)と考えます。
PGMの初めの実行時(メモリ上)では、パーティーのインスタンスにはキャラクタA,Bへの参照として情報が保持されています。
そのため、アイテムの装備画面などでキャラクタAの情報を更新した場合でも、パーティーのインスタンスにも情報が反映されています。
(もちろん、同じオブジェクトを参照しているので当たり前のことです)
つまり、戦闘を行う場合は、パーティーインスタンスの情報だけを持っていれば問題ないということです。
しかし、セーブ・ロードのためのシリアライズ/デシリアライズをかませることで、問題が発生します。
パーティーのインスタンスと、キャラクタのインスタンスをデシリアライズした結果、オブジェクトの参照関係が失われてしまうからです。
上記の例でいうと、パーティーに所属しているキャラクタAのインスタンスと、個別のキャラクタのインスタンスAが、別々に存在してしまいます。
アイテムの装備画面でキャラクタAの情報を更新した場合、パーティーのインスタンスのAには反映されなくなってしまいます。
検討したこと
対策案1.
シリアライズするクラスは、他のクラスへのオブジェクト参照は持たずに、間接的に情報を持つようにする。
上記の例でいうと、パーティーの管理はList<Character>ではなく、CharacterにIDを持たせて、そのIDを参照するList<int>として、実装する。
メリット:やりたいことは実現できそう
デメリット:直感的なロジックではなくなる
対策案2.
オブジェクトへの参照箇所を1つにする。
個別にCharacterのインスタンスを持つのではなく、List<Character>のみを管理するようにする。
メリット:やりたいことはできそう。
デメリット:アイテムの装備画面など、Characterだけを相手にしたいときは多いはず。そのようなときにノイズとなる。また、例のような簡単なケースではなく、規模が大きくなるほどに問題も膨れ上がりそう。
対策案1を採用することになるのかなと考えていますが、検討してみた対策に自信がなかったため、質問をさせていただきました。
上記の対策案の是非、他のやり方などを教えていただければ幸いです。
###補足
このデシリアライズによる問題点を調べたのですが、困っているという情報すら出てこなかったため、困惑しております。
そもそもの私の設計思想が間違っているため、この問題に突き当たっている可能性もあるのかなと考えてはいます。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/17 15:53 編集
2020/06/18 00:26
2020/06/18 00:46