Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

SerializeUtilityHybrid example for Entities 0.17?

Discussion in 'Entity Component System' started by mic-code, Jan 27, 2021.

  1. mic-code

    mic-code

    Joined:
    Feb 22, 2019
    Posts:
    1
    Have anyone got serialization working in 0.17?

    I was using something like this in 0.16
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Unity.Entities;
    4. using Unity.Entities.Serialization;
    5. using Unity.Scenes;
    6. using System.IO;
    7. using Unity.Collections.LowLevel.Unsafe;
    8.  
    9. public class SaveSystem : MonoBehaviour
    10. {
    11.     ReferencedUnityObjects g;
    12.     Data dataHold;
    13.     string json;
    14.     int i = 0;
    15.  
    16.     void Start()
    17.     {
    18.         dataHold = new Data();
    19.         g = ScriptableObject.CreateInstance<ReferencedUnityObjects>();
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         if (Input.GetKeyDown(KeyCode.F1))
    25.             save();
    26.         if (Input.GetKeyDown(KeyCode.F2))
    27.             load();
    28.     }
    29.  
    30.     public void save()
    31.     {
    32.         print("save");
    33.         var seriWorld = new World("Serialization");
    34.         EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    35.         seriWorld.EntityManager.CopyEntitiesFrom(entityManager, entityManager.GetAllEntities());
    36.  
    37.         var query = seriWorld.EntityManager.CreateEntityQuery(typeof(Prefab));
    38.         seriWorld.EntityManager.DestroyEntity(query);
    39.  
    40.         using (var writer = new StreamBinaryWriter(Application.persistentDataPath + "/save"))
    41.             SerializeUtilityHybrid.Serialize(seriWorld.EntityManager, writer, out g);
    42.  
    43.         if (g != null)
    44.         {
    45.             dataHold.Array = g.Array;
    46.             json = JsonUtility.ToJson(dataHold);
    47.             PlayerPrefs.SetString("Data", json);
    48.         }
    49.  
    50.         seriWorld.Dispose();
    51.     }
    52.  
    53.     public void load()
    54.     {
    55.         print("load");
    56.         if (g != null)
    57.         {
    58.             var data = PlayerPrefs.GetString("Data");
    59.             dataHold = JsonUtility.FromJson<Data>(data);
    60.             g.Array = dataHold.Array;
    61.         }
    62.  
    63.         var oldWorld = World.DefaultGameObjectInjectionWorld;
    64.         var newWorld = DefaultWorldInitialization.Initialize("NewWorld " + (i++));
    65.         var newManager = newWorld.EntityManager;
    66.         using (var reader = new MyStreamBinaryReader(Application.persistentDataPath + "/save"))
    67.             SerializeUtilityHybrid.Deserialize(newManager, reader, g);
    68.  
    69.         BlockLibrary.Instance.MovePrefabWorld(newWorld);
    70.  
    71.  
    72.         oldWorld.Dispose();
    73.     }
    74. }
    75.  
    I got error like
    Code (CSharp):
    1. InvalidOperationException: The previously scheduled job MatrixPreviousSystem:UpdateMatrixPrevious reads from the ComponentTypeHandle<Unity.Transforms.LocalToWorld> UpdateMatrixPrevious.JobData.LocalToWorldTypeHandle. You must call JobHandle.Complete() on the job MatrixPreviousSystem:UpdateMatrixPrevious, before you can deallocate the ComponentTypeHandle<Unity.Transforms.LocalToWorld> safely.
    and

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. Unity.Scenes.GameObjectSceneRefCount.Retain () (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Scenes/GameObjectSceneManager.cs:106)
    3. Unity.Scenes.GameObjectSceneData.Retain () (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Scenes/GameObjectSceneComponents.cs:30)
    4. Unity.Entities.ManagedComponentStore.InsertSharedComponentAssumeNonDefault (System.Int32 typeIndex, System.Int32 hashCode, System.Object newData) (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/ManagedComponentStore.cs:222)
    5. Unity.Entities.Serialization.SerializeUtility.ReadSharedComponents (Unity.Entities.ExclusiveEntityTransaction manager, Unity.Entities.Serialization.ManagedObjectBinaryReader managedDataReader, Unity.Collections.NativeArray`1[T] sharedComponentRemap, Unity.Collections.NativeArray`1[T] sharedComponentRecordArray) (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/SerializeUtility.cs:857)
    6. Unity.Entities.Serialization.SerializeUtility.DeserializeWorld (Unity.Entities.ExclusiveEntityTransaction manager, Unity.Entities.Serialization.BinaryReader reader, System.Object[] unityObjects) (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/SerializeUtility.cs:212)
    7. Unity.Scenes.SerializeUtilityHybrid.Deserialize (Unity.Entities.EntityManager manager, Unity.Entities.Serialization.BinaryReader reader, Unity.Scenes.ReferencedUnityObjects objRefs) (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Scenes/Hybrid/SerializeUtilityHybrid.cs:31)
    8. SaveSystem.load () (at Assets/Scripts/SaveSystem.cs:74)
    9. SaveSystem.Update () (at Assets/Scripts/SaveSystem.cs:32)
     
  2. PigBang

    PigBang

    Joined:
    Sep 19, 2016
    Posts:
    7
    I Have same problem.

    The problem is reproduced only in the editor. The reason is "scene Entity"(see screenshot). If serialize world without them - you can load without NullReferenceException.

    The question is what is the correct behavior in this situation.

    upload_2021-2-15_2-0-37.png
     
  3. slims

    slims

    Joined:
    Dec 31, 2013
    Posts:
    86
    I have the same issue in the editor and in release builds. Any update on this? I feel like the SerializeUtilityHybrid has had a bunch of issues since the very beginning.
     
  4. hidingspot

    hidingspot

    Joined:
    Apr 27, 2011
    Posts:
    87
    I also had similar headaches with serialization. Had it semi-working for a while but I've given up on making it all work for now, so I can move on with the project. Hoping that if/when the next entities release comes, some of this stuff will be hammered out.
     
  5. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    334
    Have the same issue. I have tried serialization in empty project and in my real project and i have got different issues.

    I have also tried to create temp world for serialization to avoid scene entity serialization by excluding this entity through entity query (see in code below), but it isn't working in editor nor in build.

    Empty project (editor/build): Serialization - goes well without any issues and there is no differ between using common or hybrid util. Deserialization - produces null ref obj error wich mentioned by thread author.
    Real project (editor): Serialization - produces error
    Tried to serialized an Entity reference however entity reference serialization has been explicitly disabled.

    Full error message
    ArgumentException: Tried to serialized an Entity reference however entity reference serialization has been explicitly disabled.
    Unity.Entities.Serialization.SerializeUtility+ManagedObjectWriterAdapter.Unity.Serialization.Binary.Adapters.IBinaryAdapter<Unity.Entities.Entity>.Serialize (Unity.Collections.LowLevel.Unsafe.UnsafeAppendBuffer* writer, Unity.Entities.Entity value) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/SerializeUtility.cs:77)
    Unity.Serialization.Binary.Adapters.BinaryAdapterCollection.TrySerialize[TValue] (Unity.Serialization.Binary.Adapters.IBinaryAdapter adapter, Unity.Collections.LowLevel.Unsafe.UnsafeAppendBuffer* buffer, TValue value) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Adapters/BinaryAdapterCollection.cs:44)
    Unity.Serialization.Binary.Adapters.BinaryAdapterCollection.TrySerialize[TValue] (Unity.Collections.LowLevel.Unsafe.UnsafeAppendBuffer* stream, TValue& value) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Adapters/BinaryAdapterCollection.cs:19)
    Unity.Serialization.Binary.BinaryPropertyWriter.WriteValue[TValue] (TValue value, System.Boolean isRoot) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Properties/BinaryPropertyWriter.cs:112)
    Unity.Serialization.Binary.BinaryPropertyWriter.Unity.Properties.Internal.IPropertyVisitor.Visit[TContainer,TValue] (Unity.Properties.Property`2[TContainer,TValue] property, TContainer& container) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Properties/BinaryPropertyWriter.cs:105)
    Unity.Properties.Property`2[TContainer,TValue].Unity.Properties.Internal.IPropertyAccept<TContainer>.Accept (Unity.Properties.Internal.IPropertyVisitor visitor, TContainer& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/Properties/Property.cs:129)
    Unity.Serialization.Binary.BinaryPropertyWriter.Unity.Properties.Internal.IPropertyBagVisitor.Visit[TContainer] (Unity.Properties.Internal.IPropertyBag`1[TContainer] properties, TContainer& container) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Properties/BinaryPropertyWriter.cs:56)
    Unity.Properties.PropertyBag`1[TContainer].Unity.Properties.Internal.IPropertyBagAccept<TContainer>.Accept (Unity.Properties.Internal.IPropertyBagVisitor visitor, TContainer& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/PropertyBags/PropertyBag.cs:180)
    Unity.Properties.PropertyBag.AcceptWithSpecializedVisitor[TContainer] (Unity.Properties.Internal.IPropertyBag`1[TContainer] properties, Unity.Properties.Internal.IVisitor visitor, TContainer& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/PropertyBags/PropertyBag.cs:92)
    Unity.Properties.PropertyBag`1[TContainer].Unity.Properties.Internal.IPropertyBagAccept.Accept (Unity.Properties.Internal.IVisitor visitor, System.Object& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/PropertyBags/PropertyBag.cs:168)
    Unity.Properties.PropertyContainer.Visit[TContainer] (TContainer& container, Unity.Properties.Internal.IVisitor visitor, Unity.Properties.Internal.VisitErrorCode& errorCode) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/Algorithms/PropertyContainer.Visit.cs:176)
    Unity.Serialization.Binary.BinaryPropertyWriter.WriteValue[TValue] (TValue value, System.Boolean isRoot) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Properties/BinaryPropertyWriter.cs:185)
    Unity.Serialization.Binary.BinaryPropertyWriter.Unity.Properties.Internal.IPropertyVisitor.Visit[TContainer,TValue] (Unity.Properties.Property`2[TContainer,TValue] property, TContainer& container) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Properties/BinaryPropertyWriter.cs:105)
    Unity.Properties.Property`2[TContainer,TValue].Unity.Properties.Internal.IPropertyAccept<TContainer>.Accept (Unity.Properties.Internal.IPropertyVisitor visitor, TContainer& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/Properties/Property.cs:129)
    Unity.Serialization.Binary.BinaryPropertyWriter.Unity.Properties.Internal.IPropertyBagVisitor.Visit[TContainer] (Unity.Properties.Internal.IPropertyBag`1[TContainer] properties, TContainer& container) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/Properties/BinaryPropertyWriter.cs:56)
    Unity.Properties.PropertyBag`1[TContainer].Unity.Properties.Internal.IPropertyBagAccept<TContainer>.Accept (Unity.Properties.Internal.IPropertyBagVisitor visitor, TContainer& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/PropertyBags/PropertyBag.cs:180)
    Unity.Properties.PropertyBag.AcceptWithSpecializedVisitor[TContainer] (Unity.Properties.Internal.IPropertyBag`1[TContainer] properties, Unity.Properties.Internal.IVisitor visitor, TContainer& container) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/PropertyBags/PropertyBag.cs:92)
    Unity.Properties.PropertyContainer.Visit[TContainer] (TContainer& container, Unity.Properties.Internal.IVisitor visitor, Unity.Properties.Internal.VisitErrorCode& errorCode) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/Algorithms/PropertyContainer.Visit.cs:189)
    Unity.Properties.PropertyContainer.Visit[TContainer] (TContainer& container, Unity.Properties.Internal.IVisitor visitor, Unity.Properties.VisitParameters parameters) (at Library/PackageCache/com.unity.properties@1.7.0-preview/Runtime/Unity.Properties/Algorithms/PropertyContainer.Visit.cs:109)
    Unity.Serialization.Binary.BinarySerialization.ToBinary[T] (Unity.Collections.LowLevel.Unsafe.UnsafeAppendBuffer* stream, T value, Unity.Serialization.Binary.BinarySerializationParameters parameters) (at Library/PackageCache/com.unity.serialization@1.7.1-preview/Runtime/Unity.Serialization/Binary/BinarySerialization.ToBinary.cs:31)
    Unity.Entities.Serialization.ManagedObjectBinaryWriter.WriteObject (System.Object obj) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/ManagedObjectBinarySerialization.cs:70)
    Unity.Entities.Serialization.SerializeUtility.WriteSharedAndManagedComponents (Unity.Entities.EntityManager entityManager, Unity.Entities.UnsafeArchetypePtrList archetypeArray, System.Int32[] sharedComponentIndicies, Unity.Entities.Serialization.BinaryWriter writer, System.Object[]& referencedObjects, System.Boolean isDOTSRuntime, Unity.Entities.EntityRemapUtility+EntityRemapInfo* remapping, Unity.Collections.NativeHashMap`2[TKey,TValue] blobAssetMap, Unity.Collections.NativeArray`1[T] blobAssetOffsets) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/SerializeUtility.cs:697)
    Unity.Entities.Serialization.SerializeUtility.SerializeWorldInternal (Unity.Entities.EntityManager entityManager, Unity.Entities.Serialization.BinaryWriter writer, System.Object[]& referencedObjects, Unity.Collections.NativeArray`1[T] entityRemapInfos, System.Boolean isDOTSRuntime) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/SerializeUtility.cs:556)
    Unity.Entities.Serialization.SerializeUtility.SerializeWorld (Unity.Entities.EntityManager entityManager, Unity.Entities.Serialization.BinaryWriter writer, System.Object[]& referencedObjects) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/Serialization/SerializeUtility.cs:413)
    Unity.Scenes.SerializeUtilityHybrid.Serialize (Unity.Entities.EntityManager manager, Unity.Entities.Serialization.BinaryWriter writer, Unity.Scenes.ReferencedUnityObjects& objRefs) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Scenes/Hybrid/SerializeUtilityHybrid.cs:17)
    FantasyTavernManager.Test.SerializationTestSystem.OnUpdate () (at Assets/Source/Test/SerializationTestSystem.cs:63)
    Unity.Entities.SystemBase.Update () (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/SystemBase.cs:412)
    Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:472)
    UnityEngine.Debug:LogException(Exception)
    Unity.Debug:LogException(Exception) (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/Stubs/Unity/Debug.cs:19)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:477)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystemGroup.cs:417)
    Unity.Entities.ComponentSystem:Update() (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/ComponentSystem.cs:114)
    Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Packages/com.unity.entities@0.17.0-preview.41/Unity.Entities/ScriptBehaviourUpdateOrder.cs:333)
    I tried to look at source code but can't understand what means IsDotsRuntime and what it depends on. Deserialization - produces editor not responding.
    Real project (build): have not tested

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Entities.Serialization;
    3. using Unity.Scenes;
    4. using UnityEngine;
    5. using Unity.Collections;
    6.  
    7. [AlwaysUpdateSystem]
    8. public class SerializationTestSystem : SystemBase
    9. {
    10.     private ReferencedUnityObjects objRefs;
    11.  
    12.     protected override void OnUpdate()
    13.     {
    14.         var globalPath = Application.dataPath + "/serialization.dat";
    15.  
    16.         if(Input.GetKeyDown(KeyCode.S))
    17.         {
    18.             using(var writer = new StreamBinaryWriter(globalPath))
    19.             {
    20. #if !UNITY_EDITOR
    21.                 var entityManager = EntityManager;
    22. #endif
    23. #if UNITY_EDITOR
    24.                 //If we in the editor then try to soleve problem by extracting all entities
    25.                 //except scene entity, which may produce error like @PigBang said in forum thread
    26.                 //https://forum.unity.com/threads/serializeutilityhybrid-example-for-entities-0-17.1046620/#post-7212172
    27.                 var serializationWorld = new World("SerializationWorld");
    28.                 var entityManager = serializationWorld.EntityManager;
    29.                 var properEntities = GetEntityQuery(ComponentType.Exclude<RequestSceneLoaded>()); //All entities except annoying scene entity which breaks deserialization
    30.                 entityManager.CopyEntitiesFrom(EntityManager, properEntities.ToEntityArray(Allocator.Temp));
    31. #endif
    32.                 try
    33.                 {
    34.                     //SerializeUtility.SerializeWorld(EntityManager, writer);
    35.                     SerializeUtilityHybrid.Serialize(EntityManager, writer, out objRefs);
    36.                     Debug.Log($"{World.Name} has been writed to {globalPath}");
    37.                 }
    38.                 catch(System.Exception ex)
    39.                 {
    40.                     Debug.LogError(ex.InnerException);
    41.                 }
    42. #if UNITY_EDITOR
    43.                 finally
    44.                 {
    45.                     serializationWorld.Dispose();
    46.                 }
    47. #endif
    48.             }
    49.         }
    50.  
    51.         if(Input.GetKeyDown(KeyCode.L))
    52.         {
    53.             using(var reader = new StreamBinaryReader(globalPath))
    54.             {
    55.                 var deserializationWorld = new World("deserializationWorld");
    56.                 try
    57.                 {
    58.                     deserializationWorld.EntityManager.PrepareForDeserialize();
    59.                     //var manager = deserializationWorld.EntityManager.BeginExclusiveEntityTransaction();
    60.                     SerializeUtilityHybrid.Deserialize(deserializationWorld.EntityManager, reader, objRefs);
    61.                     //SerializeUtility.DeserializeWorld(manager, reader);
    62.                     EntityManager.MoveEntitiesFrom(deserializationWorld.EntityManager);
    63.                     Debug.Log($"{globalPath} deserialized to {World.Name}");
    64.                 }
    65.                 catch(System.Exception ex)
    66.                 {
    67.                     Debug.LogError(ex.Message);
    68.                 }
    69.                 finally
    70.                 {
    71.                     //deserializationWorld.EntityManager.EndExclusiveEntityTransaction();
    72.                     deserializationWorld.Dispose();
    73.                 }
    74.             }
    75.         }
    76.     }
    77. }
    78.  
    Is there any person who defeat this dots serialization? Any advice? Maybe dev team can comment this and we will understand should we implement our own serialization or wait for better dots serialization code?
     
    Last edited: Jun 24, 2021
  6. scottjdaley

    scottjdaley

    Joined:
    Aug 1, 2013
    Posts:
    152
    My current solution is to use SerializeUtility instead of SerializeUtilityHybrid, at least for now. I use an approach similar to what eizenhorn describes here: https://forum.unity.com/threads/using-subscenes-like-prefabs.852619/#post-5624236

    Setup:
    1. All prefabs contain a PrefabID component with some unique identifier (FixedString32 in my case)

    On game start:
    1. Have a system store all prefab entities in a NativeHashMap keyed by their ID. I use a reactive system to ensure that all prefabs are processed exactly once.
    On save:
    1. Copy all entities to a new world that you wish to serialize.
    2. Remove all components containing BlobAssets (e.g. PhysicsCollider) and shared components (e.g. RenderMesh,
      EditorRenderData).
    3. Add corresponding tag components for each type of component or shared component removed (e.g. MissingRenderMeshTag).
    4. Call SerializeUtility.SerializeWorld()
    On load:
    1. Create a new world.
    2. Call SerializeUtility.DeserializeWorld()
    3. Move all entities to actual game world using EntityManager.MoveEntitiesFrom()
    4. A system detects entities with the missing component tags and retrieves the actual component or shared component from the entity stored in the NativeHashMap. It then restores the actual components and removes the missing component tags.
    Note: Since I store my prefabs in subscenes, there are some shared components automatically added like SceneTag and SceneSelection. I don't know what these do but my guess is something with livelink and/or the entities editor window. For now, I'm just removing these on save and not restoring them on load, but I think the same approach could be used to fetch these from a prefab on load. But everything seems to work fine without them.

    As eizenhorn mentions in their post, there are some nice advantages to a system like this. For example, you can easily change a prefabs mesh without it breaking all of your existing saves. This is because the serialized data only maps to a prefab ID, not the actual mesh.

    Let me know if the outline above isn't detailed enough and I can post some code.
     
    Last edited: Jun 24, 2021
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Go a bit lower in the api's and you can create entity prefab containers at any level you want. This is ours. PrefabConvertToEntity is a MB with a list of gameobjects that are entity prefabs. PrefabConvertToEntity instances are stored as prefabs in the hierarchy, not in the scene, and generally we have one per feature that uses entity prefabs. It's not an SO just because SO's have no value add here for the additional boilerplate/setup time needed.

    And there is a central SO database of PrefabConvertToEntity.

    https://gist.github.com/gamemachine/6e1b8f58ccdf4072a42d0baba4b57174

    We have a prefab loading system that loads all the prefabs in OnCreate. And then on the first OnUpdate calls a LoadPrefabs method on all the feature systems that have entity prefabs. And those feature systems all have a loading query that looks like so. And you can stick the entities into say a NativeHashMap using whatever key fits for how you reference stuff for instantiation.

    Code (csharp):
    1.  
    2. Entities
    3.                 .WithEntityQueryOptions(EntityQueryOptions.IncludePrefab)
    4.                 .WithoutBurst()
    5.                 .ForEach((Entity e, in YourPrefabComponent prefab) =>
    6.                 {
    7.                    
    8.                 }).Run();
    9.  
     
  8. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    334
    Thak you for answer. That approach basically describes how to implement saving with shared components, gameobjects, etc. It is all great and very helpful in development, which i will use if will get serialization works. But there is problem: i use simple serialization code i mentioned with just fresh world with 2 entities - world time entity and scene entity (potentially problematic one). Scene entity filtered with entity query and at the end i trying serialize world containing one entity without any gameobjects or problematic components. And deserializing this world of one simple entity produces
    Object reference not set to an instance of an object
    Can you please share serialization / deserialization code. Maybe we just doing something wrong.
     
  9. scottjdaley

    scottjdaley

    Joined:
    Aug 1, 2013
    Posts:
    152
    I'll try to put something together later tonight. However, I took a quick look at your code again and I think you might be using the wrong EntityManager when saving. I think it should be lower case 'entityManager' so that you use the EntityManager corresponding with your serialization world.
     
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,653
    This approach not about game objects but exactly about entities serialization and deserialization. Only GO mentioned in that approach - initial prefabs which will be converted to entity and converter itself (one GO with a list of prefabs from Addressables for conversion). The whole serialization\deserialization works exactly with entities only ;)
     
  11. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    334
    Aaaaaand yes. Just wrong EntityManager. Thank you and sorry for such a trivial mistake that i have described with such a big message

    When i say "saving with shared components, gameobects" i mean saving entities which somehow depends on gameobjects or use shared components. Basically you cut your gameobject/shared world part and replace it with ID to be able to instantiate it back on loaded entities (i'm not clearly understand what you use to map ID and GOs, but it implementation details).

    I have several questions which i can't answer by searching source code.
    * What work hybrid serializator suposed to do? Saving entities with gameobjects?
    * I have tested ComponentType field with ComponentData and it deserialize just right. But does ComponentType value and whole serialization world data will be deserialized well if i will add some new types to assembly (i'm not talking about remove/rename serialized types)
    UPD: have tested ComponentType a bit more and because it is just type index it can be shifted by another new type on assembly
     
    Last edited: Jun 26, 2021
  12. Krooq

    Krooq

    Joined:
    Jan 30, 2013
    Posts:
    180
    Hi Scott,

    Your explanation makes perfect sense.
    Although I am keen to see some example code if you have some to share please :D
     
  13. scottjdaley

    scottjdaley

    Joined:
    Aug 1, 2013
    Posts:
    152
    Hey krooq, sorry for the delay. I put together a gist that hopefully shows all the different pieces involved: https://gist.github.com/ScottJDaley/52f937c266247f221341d3fd4244e737

    I'm sure there is some way to make this approach more generic so that you don't have to manually handle each shared component or blob component. However, in my case I only have 3 components that are problematic for serialization so it hasn't been worth going down that rabbit hole just yet. Also, I like having more control on a per-component basis as it allows me to do things like use the new RenderMeshUtility to restore the RenderMesh.

    I was doing something like initially, but now I just stick all of my prefab game objects in a subscene. I like the authoring workflow with subscenes as I can immediately check the converted entity without entering playmode. Unfortunately, subscenes and addressables don't play nicely with each other at the moment, so my prefab subscenes just exist in my main scene at startup.

    Each one of my prefab entities has a custom PrefabID component that contains a unique fixed string ID. This is picked up by the PrefabSystem in the gist above.
     
    thelebaron, Arnold_2013 and Tony_Max like this.
  14. Krooq

    Krooq

    Joined:
    Jan 30, 2013
    Posts:
    180
    Thanks Scott! you are an absolute legend!
    Sometimes I feel like serialization is black magic but your code is really clear :D
     
    scottjdaley and Tony_Max like this.