FC2ブログ
    02 «1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.» 04

    ハルシオンシステムの気ままBlog

    株式会社ハルシオンシステムのメンバーが送る、UnityやらJavaやらの技術的話題から、自社開発のアプリの宣伝とかとかのブログです。ほんと気ままにいきたいと思います。更新日は毎週 月 木でっす!

     

    【ハルシオンUnityブログ】古いRuntimeVersionでシリアライズしたデータを、新しいUnityでデシリアライズする方法 

    こんにちは。
    今週は5年ぶりくらいに旅行に行ってきます。坂内っす。


    ポケットガール~受け継がれし希望~よろしくお願いします。
    URL(Android):https://play.google.com/store/apps/details?id=com.halcyon.pocketgirl3
    URL(iOS):https://itunes.apple.com/jp/app/id1539553611

    PV:



    以前Unityの古いバージョンでシリアライズしたものが、新しいUnityでデシリアライズできなくなるって話をしたと思います。
    http://halcyonsystemblog.jp/blog-entry-617.html

    API33対応のために、さらに新しいUnityにしたんですが、Script Runtime Versionがなくなってしまい、再度Deserializationができなくなりました。

    色々調べたところ、以下のことを書いているのを発見。
    「The Dictionary data can success deserialize when change the .net version, if the Dictionary data is not initialize or contain data. ie. if the dictionary data cont != 0 or not initialize the "BinaryFormatter Serialization" will not broken.」

    「ディクショナリ データが初期化されていない場合、またはデータが含まれている場合、.net バージョンを変更すると、ディクショナリ データは正常に逆シリアル化されます。つまり。辞書データが cont != 0 であるか、初期化されていない場合、「BinaryFormatter シリアル化」は壊れません。」

    だとか。

    以下の方法で解決!
    Unity2022で対応できました。

    ①以下のコードを作成

    【OlderDotNetVersionMigrationBinder.cs】

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Runtime.Serialization;
    using System;

    public class OlderDotNetVersionMigrationBinder : SerializationBinder
    {
    public override Type BindToType(string assemblyName, string typeName)
    {
    if (typeName.StartsWith("System.Collections.Generic.Dictionary"))
    {
    var readType = Type.GetType(typeName);

    return typeof(OldSaveDataDictionary<,>).MakeGenericType(readType.GenericTypeArguments);
    }
    else
    {
    return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
    }
    }

    }

    [System.Serializable]
    public class OldSaveDataDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
    public OldSaveDataDictionary() : base() { }
    public OldSaveDataDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
    {
    }

    public override void OnDeserialization(object sender)
    {
    try
    {
    base.OnDeserialization(sender);
    }
    catch { }
    }
    }


    ②ロードし、デシリアライズするところに①のバインダーをかますだけ。


    public static T Load<T>( string prefKey ){
    if (!PlayerPrefs.HasKey(prefKey)) return default(T);
    #if UNITY_IPHONE || UNITY_IOS
    System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER","yes");
    #endif

    BinaryFormatter bf = new BinaryFormatter();
    string serializedData = PlayerPrefs.GetString( prefKey );

    bf.Binder = new OlderDotNetVersionMigrationBinder();

    MemoryStream dataStream = new MemoryStream( System.Convert.FromBase64String(serializedData) );
    T deserializedObject = (T)bf.Deserialize( dataStream );

    return deserializedObject;
    }



    BinaryFormatter.BinderにOlderDotNetVersionMigrationBinderを設定してあげると、うまくいくみたい。
    ぶっちゃけ何やってるかわからんけどさw

    これでエラーが出なく、動きましたとさ。


    古いアプリをBinaryFormatterでセーブロードしてて、新しいUnityにしたら動かなくなったとかの時に役に立つかも?

    あんまりBinaryFormatter使わないほうがいいっぽいですね!
    EasySaveとかのアセット使ったほうが良さそう!


    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    コメント

    コメントの投稿

    Secret

    トラックバック

    トラックバックURL
    →http://halcyonsystemblog.jp/tb.php/1017-837bec6f
    この記事にトラックバックする(FC2ブログユーザー)