Error on play mode when SubScene is closed. It's fine when it's open

I’m upgrading my personal project to Entities 1.2.3. Everything went smoothly until I got to playing the game. This is the error:

ArgumentException: We are reading a UnityEngine.Object but the deserialized index is out of range for the given object table.
Unity.Entities.Serialization.ManagedObjectBinaryReader.Unity.Serialization.Binary.IContravariantBinaryAdapter<UnityEngine.Object>.Deserialize (Unity.Serialization.Binary.IBinaryDeserializationContext context) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/Serialization/ManagedObjectBinarySerialization.cs:246)
Unity.Serialization.Binary.BinaryPropertyReader.ReadValueWithoutAdapters[TValue] (TValue& value, System.Boolean isRoot) (at ./Library/PackageCache/com.unity.serialization@3.1.1/Runtime/Unity.Serialization/Binary/Properties/Internal/BinaryPropertyReader.cs:234)
Unity.Serialization.Binary.BinaryPropertyReader.ReadValueWithAdapters[TValue] (TValue& value, Unity.Serialization.Binary.BinaryAdapterCollection+Enumerator adapters, System.Boolean isRoot) (at ./Library/PackageCache/com.unity.serialization@3.1.1/Runtime/Unity.Serialization/Binary/Properties/Internal/BinaryPropertyReader.cs:158)
Unity.Serialization.Binary.BinaryPropertyReader.ReadValue[TValue] (TValue& value, System.Boolean isRoot) (at ./Library/PackageCache/com.unity.serialization@3.1.1/Runtime/Unity.Serialization/Binary/Properties/Internal/BinaryPropertyReader.cs:137)
Unity.Serialization.Binary.BinaryPropertyReader.Unity.Properties.IPropertyVisitor.Visit[TContainer,TValue] (Unity.Properties.Property`2[TContainer,TValue] property, TContainer& container) (at ./Library/PackageCache/com.unity.serialization@3.1.1/Runtime/Unity.Serialization/Binary/Properties/Internal/BinaryPropertyReader.cs:115)
Unity.Properties.Property`2[TContainer,TValue].Accept (Unity.Properties.IPropertyVisitor visitor, TContainer& container) (at <78ee2a1d826b40a085095f1f3dc6cfb2>:0)
Unity.Serialization.Binary.BinaryPropertyReader.Unity.Properties.IPropertyBagVisitor.Visit[TContainer] (Unity.Properties.IPropertyBag`1[TContainer] properties, TContainer& container) (at ./Library/PackageCache/com.unity.serialization@3.1.1/Runtime/Unity.Serialization/Binary/Properties/Internal/BinaryPropertyReader.cs:57)
Unity.Properties.PropertyBag`1[TContainer].Unity.Properties.IPropertyBag<TContainer>.Accept (Unity.Properties.IPropertyBagVisitor visitor, TContainer& container) (at <78ee2a1d826b40a085095f1f3dc6cfb2>:0)
Unity.Properties.PropertyBag.AcceptWithSpecializedVisitor[TContainer] (Unity.Properties.IPropertyBag`1[TContainer] properties, Unity.Properties.IPropertyBagVisitor visitor, TContainer& container) (at <78ee2a1d826b40a085095f1f3dc6cfb2>:0)
Unity.Properties.PropertyContainer.TryAccept[TContainer] (Unity.Properties.IPropertyBagVisitor visitor, TContainer& container, Unity.Properties.VisitReturnCode& returnCode, Unity.Properties.VisitParameters parameters) (at <78ee2a1d826b40a085095f1f3dc6cfb2>:0)
Unity.Properties.PropertyContainer.Accept[TContainer] (Unity.Properties.IPropertyBagVisitor visitor, TContainer& container, Unity.Properties.VisitParameters parameters) (at <78ee2a1d826b40a085095f1f3dc6cfb2>:0)
Unity.Serialization.Binary.BinarySerialization.FromBinary[T] (Unity.Collections.LowLevel.Unsafe.UnsafeAppendBuffer+Reader* stream, Unity.Serialization.Binary.BinarySerializationParameters parameters) (at ./Library/PackageCache/com.unity.serialization@3.1.1/Runtime/Unity.Serialization/Binary/BinarySerialization+FromBinary.cs:28)
Unity.Entities.Serialization.ManagedObjectBinaryReader.ReadObject (System.Type type) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/Serialization/ManagedObjectBinarySerialization.cs:227)
Unity.Entities.Serialization.SerializeUtility.ReadManagedSharedComponents (Unity.Entities.ExclusiveEntityTransaction manager, Unity.Entities.Serialization.BinaryReader reader, Unity.Collections.NativeList`1[T] sharedComponentRemap, Unity.Collections.NativeArray`1[T] unityObjects, System.Void* blobAssetBuffer) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/Serialization/SerializeUtility.cs:2031)
Unity.Entities.Serialization.SerializeUtility.EndDeserializeWorld (Unity.Entities.ExclusiveEntityTransaction manager, Unity.Entities.Serialization.DotsSerializationReader dotsReader, Unity.Entities.Serialization.SerializeUtility+WorldDeserializationStatus& status, Unity.Entities.Serialization.SerializeUtility+WorldDeserializationResult& deserializationResult, System.Int32 externalEntitiesRefRange, System.Int32 sceneSectionIndex, Unity.Collections.NativeArray`1[T] unityObjects) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/Serialization/SerializeUtility.cs:1100)
Unity.Scenes.AsyncLoadSceneOperation+AsyncLoadSceneJob.Execute () (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Scenes/AsyncLoadSceneOperation.cs:149)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/Stubs/Unity/Debug.cs:17)
Unity.Scenes.SceneSectionStreamingSystem:UpdateLoadOperation(SystemState&, AsyncLoadSceneOperation, World, Entity, Boolean) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Scenes/SceneSectionStreamingSystem.cs:655)
Unity.Scenes.SceneSectionStreamingSystem:ProcessActiveStreams(SystemState&) (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Scenes/SceneSectionStreamingSystem.cs:494)
Unity.Scenes.SceneSectionStreamingSystem:OnUpdate() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Scenes/SceneSectionStreamingSystem.cs:828)
Unity.Entities.SystemBase:Update() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/SystemBase.cs:418)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/ComponentSystemGroup.cs:723)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/ComponentSystemGroup.cs:681)
Unity.Entities.SystemBase:Update() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/SystemBase.cs:418)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/ComponentSystemGroup.cs:723)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/ComponentSystemGroup.cs:681)
Unity.Entities.InitializationSystemGroup:OnUpdate() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/DefaultWorld.cs:169)
Unity.Entities.SystemBase:Update() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/SystemBase.cs:418)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at ./Library/PackageCache/com.unity.entities@1.2.3/Unity.Entities/ScriptBehaviourUpdateOrder.cs:523)

I was able to track it down to this subscene whose only job is to collect all prefabs and convert them into entity prefabs and then manage them in a single container. It’s used such that I could query the Entity of the converted prefab by some ID. I could then instantiate that prefab using EntityCommandBuffer.Instantiate(). This scene has a MonoBehaviour holds a reference to a ScriptableObject that contains all the convertible prefabs. This MB then has a Baker that goes through all the prefabs referenced in the SO and calls GetEntity() on them.

As I was trying some things to fix it, I was able to play the game normally. But it wasn’t long that the error showed again. The only difference is when the subscene is opened or not.

I had the same problem with this subscene when I last upgraded Entities. The fix was to use DependsOn() in the baker code. Could this be related?

Have you encountered something like this? What was your fix or workaround?

I tried using a list of prefabs directly on the MonoBehaviour instead of referencing an SO. Still the same. Is this not allowed anymore?

public class EntityPrefabManagerAuthoring : MonoBehaviour {
    [SerializeField]
    private List<EntityPrefabItem> prefabs;

    public class Baker : Baker<EntityPrefabManagerAuthoring> {
        public override void Bake(EntityPrefabManagerAuthoring authoring) {
            EntityPrefabManager prefabManager = new();
     
            IReadOnlyList<EntityPrefabItem> prefabs = authoring.prefabs;
            for (int i = 0; i < prefabs.Count; ++i) {
                EntityPrefabItem item = prefabs[i];
                Entity entityPrefab = GetEntity(item.prefab, TransformUsageFlags.Dynamic);
                prefabManager.Add(item.id, entityPrefab);
            }
            
            AddComponent(GetEntity(TransformUsageFlags.None), prefabManager);
        }
    }
}

[Serializable]
public struct EntityPrefabItem {
    public string id;
    public GameObject prefab;
}

public struct EntityPrefabManager : IComponentData {
    private LinearHashMap128<int, Entity> prefabMap;

    public void Add(in FixedString64Bytes id, in Entity prefab) {
        this.prefabMap.AddOrSet(id.GetHashCode(), prefab);
    }

    public ValueTypeOption<Entity> GetPrefab(in FixedString64Bytes id) {
        return this.prefabMap.Find(id.GetHashCode());
    }

    public int Count => this.prefabMap.Count;

    public LinearHashMapBucket128<int, Entity>.Enumerator Entries => this.prefabMap.Entries;
}

From a quick glance code looks fine. I suspect one of the prefabs has something managed on a component that isn’t supported.

1 Like

There are indeed some managed objects but I use AddComponentObject() on them. This used to work. Are these no longer allowed in baking then?

I ported the managed components into unmanaged and it still happens.

So I looked at the stack trace to see if I could insert some debug logs somewhere and figure out which part of the code is causing the error. I saw SerializeUtility.ReadManagedSharedComponents() and I thought that I could log the type of the managed type being parsed. So I copied the entities package to the Package folder so I could edit it. I just added a Debug.Log() but lo and behold, it works again.

What’s going on?

You don’t actually need to make a local copy, as of about 10 unity versions ago you can now make local changes to packages in the package cache and they won’t be overwritten until package manager updates them.

Very useful for adding debugging.

1 Like

10 patch versions? Never noticed that, thanks

Oh wow, really!?

Yeah the patch note from 2022.3.28f1

Modifying assets located in immutable packages (under a project’s Library/PackageCache folder) will no longer immediately re-resolve the project’s packages, which can lead to faster iteration and allow temporary modification of those packages (for instance for testing or debugging purposes). Package Manager operations can still revert changes, so the recommended way to make changes permanent is still to embed packages prior to modifying them.

Is also in 6 but I can’t remember what version