Unity中JsonUtility序列化含二维数组的类时Chunk数据丢失如何解决?
问题原因
Unity自带的JsonUtility工具本身不支持多维数组(二维数组、三维数组等)的序列化,不管你是否把多维数组封装到可序列化类内部,只要是[,]类型的数组字段,都会被JsonUtility直接忽略。你的场景中两类二维数组都无法被识别:
- Chunk类中的
int[,] tiles二维瓦片数组 - Region类中的
Chunk[,] chunks二维区块数组
解决方案
方案1:适配JsonUtility,将多维数组转一维数组做序列化兼容
JsonUtility支持一维数组的序列化,你可以对原有类做最小改造,新增一维数组作为序列化存储字段,运行时仍使用原有二维数组操作:
[Serializable] public class Chunk { // 运行时使用的二维数组,标记为不参与序列化 [NonSerialized] public int[,] tiles = new int[CHUNK_SIZE, CHUNK_SIZE]; // 专用于序列化存储的一维数组 public int[] serializeTiles; // 序列化前调用,将二维数组转成一维 public void BeforeSerialize() { serializeTiles = new int[CHUNK_SIZE * CHUNK_SIZE]; for (int x = 0; x < CHUNK_SIZE; x++) { for (int y = 0; y < CHUNK_SIZE; y++) { serializeTiles[x * CHUNK_SIZE + y] = tiles[x, y]; } } } // 反序列化后调用,将一维数组还原为二维 public void AfterDeserialize() { tiles = new int[CHUNK_SIZE, CHUNK_SIZE]; for (int x = 0; x < CHUNK_SIZE; x++) { for (int y = 0; y < CHUNK_SIZE; y++) { tiles[x, y] = serializeTiles[x * CHUNK_SIZE + y]; } } } } [Serializable] public class Region { public Vector2Int location; // 运行时使用的二维Chunk数组,标记为不参与序列化 [NonSerialized] public Chunk[,] chunks = new Chunk[REGION_SIZE, REGION_SIZE]; // 专用于序列化存储的一维数组 public Chunk[] serializeChunks; // 序列化前调用 public void BeforeSerialize() { serializeChunks = new Chunk[REGION_SIZE * REGION_SIZE]; for (int i = 0; i < REGION_SIZE; i++) { for (int j = 0; j < REGION_SIZE; j++) { chunks[i,j].BeforeSerialize(); serializeChunks[i * REGION_SIZE + j] = chunks[i, j]; } } } // 反序列化后调用 public void AfterDeserialize() { chunks = new Chunk[REGION_SIZE, REGION_SIZE]; for (int i = 0; i < REGION_SIZE; i++) { for (int j = 0; j < REGION_SIZE; j++) { chunks[i, j] = serializeChunks[i * REGION_SIZE + j]; chunks[i,j].AfterDeserialize(); } } } }
原有序列化逻辑调整为:
Region region = new Region(); region.location = new Vector2Int(x, y); for (int i = 0; i < REGION_SIZE; i++) { for (int j = 0; j < REGION_SIZE; j++) { region.chunks[i, j] = GenerateChunk(); } } // 序列化前先执行数组转换 region.BeforeSerialize(); string regionJson = JsonUtility.ToJson(region);
反序列化时先调用JsonUtility.FromJson<Region>()得到实例,再执行实例的AfterDeserialize()方法即可还原所有数据。
方案2:更换JSON序列化库
如果你不想改动原有数据结构,可以使用Newtonsoft.Json(Unity 2020+已内置该库,可直接在PackageManager中导入),该库原生支持多维数组序列化,无需修改现有Chunk、Region类,直接调用序列化方法即可:
// 直接序列化,无需其他前置处理 string regionJson = JsonConvert.SerializeObject(region); // 反序列化调用 Region region = JsonConvert.DeserializeObject<Region>(regionJson);
内容的提问来源于stack exchange,提问作者David Meyenberg
相关产品推荐
相关产品推荐

