XML serialisaton. Error: XmlException: Root element is missing.

MaksimMaltsev

Member
Joined
Mar 29, 2021
Messages
9
Programming Experience
1-3
Hi all. I am making a game like minecraft. I need to keep the world when the player exits the game. Chunk (it is a place 16 by 16 blocks) and world contain a lot datas, that don't serialize can. so i have created classes WorldData and ChunkData, that contain only serializable varibles. But i have a error when world is serialized: XmlException: Root element is missing. This is the code:

WorldData:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Xml.Serialization;

public class WorldData{
    public static XmlSerializableDictionary<Vector2, ChunkData> bloksData = new XmlSerializableDictionary<Vector2, ChunkData>();//deserialized dictionary
    public static XmlSerializableDictionary<VectorConventer, ChunkData> bloksConvertData = new XmlSerializableDictionary<VectorConventer, ChunkData>();//serializible dictionary

    //get deserialized world <Vector2, ChunkData>
    public static XmlSerializableDictionary<Vector2, ChunkData> Deserialization(){
        XmlSerializer WorldXML = new XmlSerializer(typeof(XmlSerializableDictionary<VectorConventer, ChunkData>));
        using (FileStream fs = new FileStream("New_World.xml", FileMode.OpenOrCreate)){
            bloksConvertData = (XmlSerializableDictionary<VectorConventer, ChunkData>)WorldXML.Deserialize(fs); //Error. XmlException: Root element is missing.
        }
        foreach(var item in bloksData){
            bloksConvertData[new VectorConventer(item.Key)] = item.Value;
        }
        return bloksData;
    }

    //serialisation
    static void SaveWorld(){
        foreach(var item in bloksData){
            VectorConventer keyVec = new VectorConventer(item.Key);
            bloksConvertData[keyVec] = item.Value;
        }
        XmlSerializer WorldXML = new XmlSerializer(typeof(XmlSerializableDictionary<VectorConventer, ChunkData>));
        using (FileStream fs = new FileStream("New_World.xml", FileMode.OpenOrCreate)){
            WorldXML.Serialize(fs, bloksConvertData);
        }
    }

    //add new chunk to save
    public static void AddNewChunk(Vector2 position){
        bloksData.Add(position, new ChunkData());
    }
}
CunkData:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.IO;
using System.Runtime.Serialization;
using System.Xml.Serialization;


[Serializable]
public class ChunkData
{
    public ChunkData(){}
    public BlockType [] bloks = new BlockType [165888];
    public bool isGenetated;
    
    public float posX;
    public float posZ;
    
    public void SetValues(BlockType [ , , ] bloks3d, Vector2 position){
        bloks = ToSimpleArray(bloks3d);
        posX = position.x;
        posZ = position.y;
    }

    public BlockType [ , , ] GetArray(){
        return To3dArray(bloks);
    }
    //to three dimensional array
    private static BlockType [ , , ] To3dArray(BlockType [] Array){
        BlockType [ , , ] resultArray = new BlockType [18, 512, 18];
        for(int i = 0; i < 18; i++){
            for(int j = 0; j < 512; j++){
                for(int k = 0; k < 18; k++){
                    resultArray[i, j, k] = Array[i*512*18 + j*18 + k];
                }
            }
        }
        return resultArray;
    }
    //to one dimensional array
    private static BlockType [] ToSimpleArray(BlockType [ , , ] Array)
    {
        BlockType [] resultArray = new BlockType [18 * 512 * 18];
        int index = 0;
        BlockType [] SimpleArray = new BlockType [27];
        for(int i = 0; i < 18; i++){
            for(int j = 0; j < 512; j++){
                for(int k = 0; k < 18; k++){
                    SimpleArray[index] = Array[i, j, k];
                    index++;
                }
            }
        }
        return resultArray;
    }
}
World:
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;

public class World : MonoBehaviour
{
    public static Dictionary<Vector2, Chunck> chunks = new Dictionary<Vector2, Chunck>();

    public List <Vector2> toGenerate;
    public List <Vector2> toDelete;
    public static XmlSerializableDictionary<Vector2, Chunck> loadedChuncks = new XmlSerializableDictionary<Vector2, Chunck>();
    //<...>

    void Start() //called when the game starts
    {
        LoadWorld();
        //<...>
    }

    public void LoadWorld(){
        Dictionary<Vector2, ChunkData> world = WorldData.Deserialization();
        foreach (var item in world)
        {
            loadedChuncks.Add(item.Key, new Chunck());
            loadedChuncks[item.Key].Data = item.Value;
            loadedChuncks[item.Key].SetValues();
        }
    }
    //<...>
}
Chunck:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Chunck : MonoBehaviour
{
    public ChunkData Data;
    public BlockType [ , , ] bloks  = new BlockType [18, 512, 18]; //data of the blocks in the chunk
    
    public Vector2 Position = new Vector2();
    //<...>

    //generation
    public void ChunckGeneration(){
        //<...>
    }

    public void Optimize() //build voxels
    {   
        //<...>
    }

    //set data to serialisation
    void ChunckToSave(){
        Data.SetValues(this.bloks, Position);
    }

    //get data
    public void SetValues(){
        this.bloks = Data.GetArray();
        this.isGenetated = false;
    }
}
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
3,762
Location
Chesapeake, VA
Programming Experience
10+
You are still still serializing the same amount of data, not just the data that matters.
 
Top Bottom