Search Unity

Arrays are not supported in IComponentData class

Discussion in 'Entity Component System' started by alexandre-fiset, Nov 26, 2019.

  1. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    If SomeClassComponentData has an array in it, and is followed by any other AddComponentData of a struct, the following error will be thrown:

    ArgumentException: Requested value outside bounds of UnsafeAppendOnlyBuffer. Remaining bytes: {Buffer->Size - m_Offset} Requested: {structSize}

    Some dummy code to illustrate.

    Code (CSharp):
    1. public class TestAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    2. {
    3.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    4.     {
    5.         dstManager.AddComponentData(entity, new SomeClassComponentDataWithArray());
    6.         dstManager.AddComponentData(entity, new SomeStructComponentData());
    7.     }
    8. }
    The above does not work, while the below does:

    Code (CSharp):
    1. public class TestAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    2. {
    3.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    4.     {
    5.   dstManager.AddComponentData(entity, new SomeStructComponentData());
    6.         dstManager.AddComponentData(entity, new SomeClassComponentDataWithArray());
    7.     }
    8. }
    I am not sure if this is intended, but I don't know why the order matters and I believe the error message should be more clear.
     
  2. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    ComponentData only support fixed size buffers. Maybe what you are looking for is DynamicBuffer.

    Edit: totally missed the 'class' part.
     
    Last edited: Nov 27, 2019
  3. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    DynamicBuffers can't store MonoBehaviours.
    My workaround at the moment is to use ISharedComponentData instead.
     
  4. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    in the new 0.2 Entities version it's possible to use Managed types inside ComponentData types but it comes with a cost.


    Added support for managed IComponentData types such as class MyComponent : IComponentData {} which allows managed types such as GameObjects or List<>s to be stored in components.
    Users should use managed components sparingly in production code when possible as these components cannot be used by the Job System or archetype chunk storage and thus will be significantly slower to work with.
    Refer to the documentation for component data for more details on managed component use, implications and prevention.


    More Details:
    https://docs.unity3d.com/Packages/com.unity.entities@0.2/changelog/CHANGELOG.html
     
  5. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    @Opeth001 : I know about that, the point of my post is to say that storing List (or Array) has a major limitation: It has to be part of the last component added to an Entity, otherwise it throws errors.
     
  6. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    to be honest i didn't try it for now.

    did you implemented the IEquatable<T> interface and added the override for Object.GetHashCode() for your Managed ComponentData ?
     
  7. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    Should I? I did for ISharedComponentData as suggested by the console, but none of these messages appeared for the managed component date :(

    From the release notes:
    Managed IComponentData no longer require implementing the IEquatable<> interface and overriding GetHashCode(). If either function is provided it will be preferred, otherwise the component will be inspected generically for equality.
     
  8. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    I’m not 100% sure but this is what is written in their documentation of the 0.2 version.

    Managed IComponentData must implement the IEquatable<T> interface and override for Object.GetHashCode(). As well, for serialization purposes, managed components must be default constructible.
    link
     
  9. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    class IComponentData
    Thats not accurate.

    class IComponentData does not require GetHashcode or IEquatable.

    You can have an array in class IComponentData and it will get serialized.

    Unfortunately we yesterday found a bug in the serializer (This will be fixed in next entities release)
    For now you should be able to add another field after the array and then the bug should disappear. Sorry about that...
     
    alexandre-fiset and florianhanke like this.