Serialization and Deserialization issues.

Hello community!

We’ve been having some issues with deserializing our entities. At the moment we have 2 major issues that we want some help with. 1) Losing our child component information after deserializing. 2) unclear on how to save the out object[ ] that is made when serializing.

  1. The main issue here is when we load the save file the parent entities lose their Child BufferComponent. This leads to not being able to properly rotate or move our entity because its children are no longer attached. Is this just something we need to work around? We have tried to re-add the Child buffer, but we have had no luck in being able to do this.

  2. When Serializing the world, it seems we need to save the out Object[ ] as well so we can Deserialize at a later time. Saving and Loading on the same play session works fine, 1 time. But trying to do so after the play session or 2 times throws errors on being unable to use that Object[ ]. How would we go about saving this and why isn’t this just done by default?

Any help on these topic would be amazing. Code is below.

 private void SaveMethod()
    {
        using var saveWorld = new World("saveWorld", WorldFlags.Staging);

        using var entityArray = saveQuery.ToEntityArray(Allocator.Temp);

        var entityRemap = new NativeArray<EntityRemapUtility.EntityRemapInfo>(EntityManager.EntityCapacity, Allocator.Temp);
       
        saveWorld.EntityManager.CopyEntitiesFrom(EntityManager, entityArray);

        using var streamWriter = new StreamBinaryWriter($"{Application.dataPath}/saveData");
       
        SerializeUtility.SerializeWorld(saveWorld.EntityManager, streamWriter, out objectOuputArr, entityRemap);
       
        PlayerPrefs.SetString("objArray", objectOuputArr.ToString());
        PlayerPrefs.Save();
       
    }

    private void LoadMethod()
    {
        var objArray = PlayerPrefs.GetString("objArray", objectOuputArr.ToString());
       
        using var loadWorld = new World("loadWorld", WorldFlags.Staging);

        var loadEntityManager = loadWorld.EntityManager;

        var eeTrans = loadEntityManager.BeginExclusiveEntityTransaction();
       
        using var streamReader = new StreamBinaryReader($"{Application.dataPath}/saveData");
       
        SerializeUtility.DeserializeWorld(eeTrans, streamReader, objectOuputArr);
       
        loadEntityManager.EndExclusiveEntityTransaction();

        EntityManager.CopyAndReplaceEntitiesFrom(loadEntityManager);
}

The Child buffer should automatically be maintained by Unity and you should never have to touch it. It is SystemState so it should only be created and maintained at runtime and not be serialized. However, there is a bug where the ParentSystem’s change filtering generates false negatives, which cause the child buffer to not get added or updated. To fix this, after deserializing, loop over all the newly deserialized chunks which contain a Parent component. Then get write access to the Parent array. You don’t need to actually do anything with the array, but this marks the Parent components as possibly changed allowing for the filter to work correctly.

Hi DreamingImLatios,

I just tried your suggestion and didn’t get any new results, but i may be doing it incorrectly. I’m creating the query after load as the following:

using var parnetQuery = EntityManager.CreateEntityQuery(ComponentType.ReadWrite<Parent>()).ToEntityArray(Allocator.Temp);
        Debug.Log("Parent Length: " + parnetQuery.Length);

I am getting a length on this query. Am I doing this incorrectly?

No, you aren’t doing anything which updates the change version. Try scheduling a job like this:

[BurstCompile]
struct UpdateParentChangeVersionsJob : IJobEntityBatch
{
    public ComponentTypeHandle<Parent> parentHandle;

    public void Execute(ArchetypeChunk batchInChunk, int batchIndex)
    {
        batchInChunk.GetNativeArray(parentHandle);
    }
}

Thank you DeamingImLatios, this help rebuild the child buffer! Now we just need to figure out how to save the object[ ].

Thank you again!

The object[ ] is essentially the data Unity does not know how to serialize and/or deserialize. Use any serialization method for the data that is representing and recreate it in session 2 based on that.