Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Generic Components

Discussion in 'Entity Component System' started by orionburcham, Jan 27, 2019.

  1. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    488
    I was amazed to find that generic IComponentData seem to be work. For example:
    Code (CSharp):
    1. public struct MyGenericData<T> : IComponentData
    2. {
    3.     public T value;
    4. }
    ...can be added to an entity just fine, using EntityManager.AddComponentData<T>(). It even shows up in the Inspector properly, displaying 'value' as the correct type.

    I would assume this is not officially supported, and that it may be explicitly prevented in the future. But does anyone out there know more?

    Thanks!
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    And why it could not work :) Struct is value type and for IComponentData you also use blittable value types for T, compiler in result code just creates struct for all unique used value types. For example you use somewhere in you code:
    Code (CSharp):
    1. MyGenericData<int> intGen;
    2. MyGenericData<float> floatGen;
    After compile it will be like if you write (of course in simplified explanation):
    Code (CSharp):
    1. public struct MyGenericData_INT : IComponentData
    2. {
    3.     public int value;
    4. }
    5.  
    6. public struct MyGenericData_FLOAT : IComponentData
    7. {
    8.     public float value;
    9. }
    10.  
    11. MyGenericData_INT intGen;
    12. MyGenericData_FLOAT floatGen;
    After compilation generic value types not exists like pure dynamic generics, they compiles to specific types.
    https://docs.microsoft.com/en-US/dotnet/csharp/programming-guide/generics/generics-in-the-run-time
     
  3. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    How do you come up with the idea that it is not supported?

    The only thing what won't work is, autocreation of generic system. They have to be added manually to the playloop. But generic structs are common tools and nothing special at all.

    Anyway have fun :)
     
  4. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    I think the confusion comes from the fact that in 'regular' C# (i.e. microsoft .NET) generic types, including structs, are never considered 'blittalbe'. You can't get a pointer to a generic type, etc.
     
  5. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Why isn't a generic struct not blittable?
    Structs are only non-blittable if they contain non-blittable types. E.g. if the generic type is non-blittable.
    https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types
     
  6. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
  7. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Yes, that is correct. You can't do T* directly. But you can do void* or byte* (off-topic).
    But there is the relevance to blittability of components?

    I'm a little bit confused. Or do you mean that ecs can't handle T*?
    If so.. internal they use void* in combination with component size.
     
    Deleted User likes this.
  8. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    IIRC in C# 7.3 you can get a generic pointer if the type is blittable and you have used the unmanaged constraint.

    []'s
     
    Spy-Shifty likes this.
  9. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    488
    Great discussion, I’ve learned a lot.

    The reasons I thought this might not be supported boil down to:

    1. The blittability of components (already discussed a lot here)

    2. Serialization concerns (seems like that should actually be fine, since they’re value types)

    3. General usability. For example, generic systems like
    public class MySystem<T> : ComponentSystem
    aren’t supported (Unity won’t instantiate them), which makes sense. And if you adhere to a strict separation of data and logic, then you generally can’t have functions in your structs that take advantage of their generic types. So generic components may have a more limited usefulness than nighttime me originally thought. :)

    Though it’s a neat feature that they are supported, and maybe situations will emerge in which they are useful.
     
    Last edited: Jan 28, 2019
  10. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546

    Thank, I've a good usecase for generic components and systems: (just for inspiration)

    I use this for my Networkstack from the FPS Sample. So I have a generic SequenceBuffer component where I store the state of components for a specific time.

    Code (CSharp):
    1.  
    2. struct SequenceInfo<T> : IBufferedData where T : struct {
    3.     public T Data;
    4.     public int Sequence;
    5. }