Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Multiple AddComponentData in the same frame.

Discussion in 'Entity Component System' started by Lieene-Guo, Mar 9, 2020.

  1. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
    I have a simple project implementing a movement system.
    I want to move objects by Speed. and remove Speed ComponentData on zero speed. So my query will no longer give me this "sleeping" Entity. When I want to let it move again. I can Use EntityCommandBuffer.AddComponent(Speed).

    But the problem is ECB can only do add/remove. there is no conditional add or read=>change=>and set capability. So when adding Speed ComponentData in multiple places from logic code in the same frame. there will be only one speed that applies but what I want is the sum of all these speeds.

    When Speed component presents, read and set is okay. But when it is removed somehow. how can I do an addComponent and read=>write in parallel?

    Or Is there any other pattern that I can use?
     
    Last edited: Mar 9, 2020
  2. Curlyone

    Curlyone

    Joined:
    Mar 15, 2018
    Posts:
    41
    Hi.

    What i would do is:

    I would have a Tag component which lets say called "OnTheMove".
    I would make my movement system run when both SpeedComponent and OnTheMove are present in entity.

    Then i would run my speed modifiers, if any of them wants to move the object i would add OnTheMove tag to entity and modify SpeedComponent's speed value.
    And at the start of every frame(or after movement system) i would remove OnTheMove tag.

    However, there are 2 issues with this solution, first is there will be 1 frame lag, second is there will be multiple OnTheMove tag added that overwrites each other(depending on how many modifiers wanted to move the object) in Sync point which could introduce some 'wasted' miliseconds and as well as a Sync point itself.

    2nd solution could be have a dynamic buffer that speed modifiers write to, then process this buffer and set SpeedComponent and add OnTheMove tag accordingly, but that would mean the system that does this processing would run for every entity whatever they are moving or not, which looks like you want to avoid in the first place.

    In my opinion, if your object is frequently moving around, you can deal with sleeping entities.

    But perhaps a more experienced person would know much better than me.
     
  3. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    825
    Use EntityManager to check if the entity have the component, then you can add/remove with ECB
     
  4. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
    I am trying to do it in parallel job. where EntityManager can not be used.
     
  5. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,695
    I will be hitting this type of scenario very soon. Is there a way to leverage filters to avoid structural changes altogether.
     
  6. TheGabelle

    TheGabelle

    Joined:
    Aug 23, 2013
    Posts:
    242
  7. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
    I have made an AddOrCombineComponentCommandBufferSystem<T>(name as verbose as ECS itself) that act as EntitiyCommandBufferSystem, but it can do AddComponentData if not present or else CombineComponentData.

    The T is an IComponentData that implements ICombineAble<T>, so the system knows how to combine them.

    use:
    public CommandBuffer GetCommandBuffer()
    to get a CommandBuffer from the system.
    use:
    public void AddOrCombineComponent(Entity entity, T data)
    to add or combine Component data. target component data
    CommandBuffer also has a ToConcurrent() API to work in jobs.

    PS. DeferedEntitySystem attached is a System to track Entity that Return by EntityCommandBuffer.CreateEntity().
    Details can be found here: https://forum.unity.com/threads/api-usability.550450/page-7
    Look like this DeferedEntity is still useful when Entity from ECB.Create is used outside
     

    Attached Files: