使用ISerializationCallbackReceiver解决HashSet/Dictionary无法序列化的问题

Posted thpgames

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用ISerializationCallbackReceiver解决HashSet/Dictionary无法序列化的问题相关的知识,希望对你有一定的参考价值。

自定义数据类被标记为[Serializable]后, 像 HashSet<T> / Dictionary<T> 类型的数据依然无法被Unity自动序列化。一种办法是内部再存一个数据列表(一般是List<T>类型),序列化之前先把数据倒腾到List<T>中, 在运行时加载后再执行自己写的 "Init()" 之类的函数将数据从List<T>中倒腾到 HashSet<T>中。实际上,对于这种情况,Unity已经提供了一个处理方式: ISerializationCallbackReceiver。自定义的数据类只需要实现这个接口,Unity自己就会在序列化/发序列化时自动执行对应操作。

该接口很简单,在Unity中定义如下:

    [RequiredByNativeCode]
    public interface ISerializationCallbackReceiver
    {
        //
        // 摘要:
        //     Implement this method to receive a callback after Unity deserializes your object. //将在Unity反序列化你的对象后被执行。
        [RequiredByNativeCode]
        void OnAfterDeserialize();
        //
        // 摘要:
        //     Implement this method to receive a callback before Unity serializes your object. //将在Unity序列化你的对象之前被执行。
        [RequiredByNativeCode]
        void OnBeforeSerialize();
    }

当然,并非只有集合类才能这样操作。以下是一段简单的示例代码:

 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 using System;
 4 
 5 namespace THP.ExampleCode.SerializationCallback
 6 {
 7     [Serializable] 9     public class Items : ISerializationCallbackReceiver
10     {
11         /// <summary>
12         /// dictionary of items. key: Item.Id value: Item
13         /// </summary>
14         public Dictionary<int, Item> ItemDict = new Dictionary<int, Item>();
15         [SerializeField]
16         List<Item> itemList;
17 
18         public void OnAfterDeserialize()
19         {
20             foreach (var item in itemList)
21             {
22                 ItemDict.Add(item.Id, item);
23             }
24         }
25 
26         /// <summary>
27         /// 将在序列化之前执行。
28         /// </summary>
29         public void OnBeforeSerialize()
30         {
31             itemList = new List<Item>();
32             foreach (var kv in ItemDict)
33             {
34                 itemList.Add(kv.Value);
35             }
36         }
37     }
38 
39     [Serializable]
40     public class Item : ISerializationCallbackReceiver
41     {
42         [NonSerialized]
43         public int Id;
44         [NonSerialized]
45         public string Name;
46         // ... other infos
47         [SerializeField]
48         private byte[] compressedByteArray;
49 
50         public void OnAfterDeserialize()
51         {
52             CompressToolAtSomewhere.DecompressItemInfo(compressedByteArray, this);
53         }
54 
55         public void OnBeforeSerialize()
56         {
57             compressedByteArray = CompressToolAtSomewhere.CompressItemInfo(this);
58         }
59     }
60 }

 

以上是关于使用ISerializationCallbackReceiver解决HashSet/Dictionary无法序列化的问题的主要内容,如果未能解决你的问题,请参考以下文章

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份