Search Unity

Feedback We need a way to drop generic component payloads onto entities

Discussion in 'Entity Component System' started by kstothert, May 20, 2019.

  1. kstothert

    kstothert

    Joined:
    Dec 8, 2016
    Posts:
    68
    I keep bumping up against this issue. What would be ideal is someway to package components so they can be copied from one entity to another generically. This would solve many current issues i've been having.

    - Pickups could store the component "payload" and add it to the player entity when it collides with the pickup
    - AI behaviours could use generic references to "Task" components and those could be added to the controller without knowing which specific task component was being added.

    Basically anytime we have an interaction between entities where one entity has some arbitrary set of components that we want added or removed from the other entity. Personally I love the performance of ECS but there are many cases where having of some form of generics would outweigh those performance benefits. We need an escape hatch for these cases.
     
    Last edited: May 21, 2019
  2. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Something like this?

    EntityManager.CopyComponent(Entity src, Entity dst, ComponentType type);
     
  3. kstothert

    kstothert

    Joined:
    Dec 8, 2016
    Posts:
    68
    that would work if the component it was copying was actually a payload of multiple components. That way i would just copy the payload component and i would get whatever components had been packaged up for me. Otherwise I have to know in advance what components I want to copy over which would require unique systems for all configurations.
     
  4. kstothert

    kstothert

    Joined:
    Dec 8, 2016
    Posts:
    68
    It would be cool if we had a notion of interfaces for components so that I could flag certain components as being part of a group. Then I could get cool features like the ability to prevent an entity from having two components of the same group (useful for states, ai, etc)
     
  5. kstothert

    kstothert

    Joined:
    Dec 8, 2016
    Posts:
    68
    Also this way a component could store another component without knowing which specific component it was, just that it was a member of a certain group (or interface)
     
  6. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Do you have a specific proposal for an API?
     
  7. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Maybe:
    EntityManager.CopyComponent(Entity src, Entity dst, EntityArchetype types);

    var archetype = EntityManager.CreateArchetype(typeof(Translation), typeof(MyOtherComponent));
    EntityManager.CopyComponent(Entity src, Entity dst, archetypes);


    This is a compact way of representing a bunch of component types together. You could create it
     
    Xerioz likes this.
  8. kstothert

    kstothert

    Joined:
    Dec 8, 2016
    Posts:
    68
    yea i'll play with the archetype trick, thanks.

    My ideal solution would be some sort of "managed" layer on top of DOTS that gave these and other convenience features for less performance oriented games. The approach you and your teams have taken toward performance doesn't always make life easier for us developers. I love DOTS and all the work you guys are doing though, dont get me wrong, I just crave some form of generics to make my life easier.
     
  9. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Sure. Optimally we are looking for useful API's that make writing game code easier that are also performant.

    We are also happy to build scaffolds on top of high performance code. Like Entities.ForEach.

    in any case, first comes what you are trying to do. Is it really literally just copying a set of components from one entity to another?
     
  10. kstothert

    kstothert

    Joined:
    Dec 8, 2016
    Posts:
    68
    Well no, my issue centers around properly packaging and distributing ai behaviours. I'm working on a GOUP (goal oriented utility planner) it combines utility based goal selection with ranked task pathways.

    I would like to be able to build up an AI entity by simply adding an AIController Component and a buffer of tasks which I would use as a stack. This way I could select the current goal based on utility then add the right buffer of tasks that represents the lowest cost path to achieve it. So I would pop the top task off the buffer and add it as a component to my entity but I wouldn't know which task it was.
     
  11. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    It seems you want to have some sort of EnumComponent that will respect enum in Rust

    https://doc.rust-lang.org/rust-by-example/custom_types/enum.html

    It is just TypeSafe C++ Union

    This way you can pack all task types inside one EnumComponent and work on it without changing EntityArchetype and all this type safe :)

    I have done thins thing for bots in our game. In pure C# it looks ugly (because I need to manage same structure sizes for all enum variants by hand) but usable. Bots have many states (like doing different tasks in your case) and based on this state I just run different method.

    Making EnumComponent first class citizen of ECS like IBufferElementData which calculate total component size itself will be great :)
     
    Last edited: May 21, 2019
  12. Richay

    Richay

    Joined:
    Aug 5, 2013
    Posts:
    122
    Did this ever come close to fruition? I'm at a point where I need to copy all components from one entity to another.

    For context, I'm building a system which allows a command-buffered entity to spawn a gameobject prefab. My process is:
    - Reference entity has only one component: LinkedMonoPrefabData.
    - LinkedMonoPrefabData has only one field: InstanceId (int).
    - At runtime, I add all non-DOTS-compliant prefabs into a dictionary, keyed by their instance ID.
    - My entities which will instantiate gameobject prefabs are instantiated when necessary in a command buffer. When these entities are created, I also attach relevant component data, which can be literally anything (initial translation, physics velocity, number of apples in hands, etc)
    - A system, InstantiateMonoPrefabSystem, runs for each LinkedMonoPrefabData.

    Code (CSharp):
    1. Entities
    2.     .ForEach((Entity entity, in LinkedMonoPrefabData prefabData) =>
    3.     {
    4.         if (GameBehaviour.Instance.PrefabDictionary.TryGetValue(prefabData.PrefabInstanceId, out var gameObjectPrefab))
    5.         {
    6.             var instanceEntity = EntityManager.Instantiate(gameObjectPrefab);
    7.  
    8.             var components = EntityManager.GetComponentTypes(entity, Allocator.Temp);
    9.             for (int i = 0; i < components.Length; i++)
    10.             {
    11.                 // I would love for this method to exist.
    12.                 EntityManager.CopyComponent(entity, instanceEntity, components[i]);
    13.             }
    14.             components.Dispose();
    15.         }
    16.     })
    17.     .WithoutBurst()
    18.     .Run();
    If there's a more elegant way of doing this, I'd love to know.