#Cannot use NativeContainers inside components in build.

1 messages · Page 1 of 1 (latest)

weak bolt
#

Using Native Collections in the editor works fine. It forces you to add [ChunkSerializable]to the component to be able to add it in baking, but it works.

However, the built player doesn't even start. Checking the log you can see there's a component whose TypeIndex was not found for its given hash.

Cannot find TypeIndex for type hash 16496509230482686058. Check in the debug file ExportedTypes.log of your project Logs folder (<projectName>/Logs) the corresponding Component type name for the type hash 16496509230482686058. And ensure your runtime depends on all assemblies defining the Component types your data uses.

I'm using several components with Native Collections in my project, and turned out that every component mentioned in the log, that has issues being "loaded" was one of the components using Native Collections.

I made a new project trying to reproduce the error and it was as easy as adding a simple component that has a collection and adding it to an entity via baking. Here are the scripts.

Is there a known workaround or fix? Is there something I'm doing wrong about the usage of these components?

Unity Editor 2022.3.2 & 2022.3.5
Unity Entities 1.0.11

warped sundial
#

Serializing native containers in components is not allowed since we do not do anything special to handle the memory allocations the containers point to. Serializing a component with a pointer in it ends up serializing just the ptr, which will be invalid when you deserialize and not contain any of your elements. This is why we don't allow serializing containers / any pointers in general. If you are fine with that limitation you can use [ChunkSerializable] and handle loading content into your container (in addition to making your container valid again since the invalid ptr will make the container look to be IsCreated when it isn't actually).

The issue you are hitting with failing to deserializing in player builds is due to player builds not containing AtomicSafetyHandles. NativeParallelHashMap contains a safety handle in editor which won't exist in player builds, so the component ends up with a different memory layout between editor and player builds and we fail to deserialize since there is no component type that looks the same in the player build as we saw in the editor build.

If you really want to serialize a NativeParallelHashMap in a component and handle the initialization of the container and loading of all the elements it contains, you can avoid the deserialization error above by using the UnsafeParallelHashMap which does not container a safety handle.

weak bolt
#

Hi,
I'm actually not serializing anything in native containers, I just want to add the component in baking to avoid having to make specialized systems just to add those components at runtime. But at baking there is no data in any of them.

So replacing the containers with their Unsafe counterpart just to make it "look" the same in both editor and build would avoid this issue?

weak bolt
warped sundial
#

Components all have a StableTypeHash (e.g. TypeManager.GetTypeInfo<Component>().StableTypeHash) which identifies the type layout of the type to know if the data serialized will be valid when we deserialized. Unsafe containers have the same type layout in both Editor and Player builds so that will be a way forward.

The reason why Native containers have a different layout is due to Player builds do not have the AtomicSafetyHandle defined. This is a Unity engine specific difference (rather than Entities) so unfortunately Native containers will not be serializable until at least a new Unity release.

little stirrup
warped sundial
#

No, such a change would be quite big and would need to be in a new major release of Unity

weak bolt
#

Alright. Thank you!

And please add all this to the documentation, I don't think is something obvious, specially considering the log error is not super informative.

wild quarry
#

If you really want to serialize a NativeParallelHashMap in a component and handle the initialization of the container and loading of all the elements it contains, you can avoid the deserialization error above by using the UnsafeParallelHashMap which does not container a safety handle.
@warped sundial What is the catch of this method?