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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Remove ComponentType from all entities?

Discussion in 'Entity Component System' started by gilley033, Aug 17, 2018.

  1. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,151
    Hello, I was wondering what the best way to remove a single component type from all entities that have it.

    Here's my use case:

    I am planning on running a custom deterministic physics engine that will utilize a system loop to iterate each physics "tick". All is well during a full physics tick, but on every frame there is some left over time (for example, say the tick fixed time step is .002, but Time.deltaTime is .005. This would produce two full ticks and a partial tick of .001).

    To account for this, I perform a special system iteration that basically involves updating the rendered positions of the physics objects without changing the physics positions.

    However, in order to reuse the the same systems used in the regular system loop (code reuse!), I need them to be able to change the physics position at will; i.e., they should not know that a special iteration is occuring. So my solution is to create a special component that holds the pre-iteration positions and add it to each physics object. Then the systems can work as normal, and after the rendered positions are updated to the values stored in the physics position components, I have a system that detects the existence of the pre-iteration positions and uses those to reset each entities physics position.

    Now here's the question. What is the best way to remove the pre-iteration position components, since they are no longer needed (and in fact, they need to removed, as otherwise the next full physics tick would end with the physics positions being reset again)?

    The actual work of resetting the physics positions is being performed by a JobComponentSystem, so I understand that I could create a BarrierSystem and use a command buffer to call RemoveComponent on each entity within the Execute method, however that seems like a bad way to go about things considering I know I want to remove this component from all entities that contain it.

    Is there no way to do a full removal of this component from all entities? What would be even cooler is a temporary component that is flushed from all entities at the end of the frame. Does such a thing exist? How do people deal with temporary components like these?

    Thanks!
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,559
    Why do you consider this to be bad way?

    I think this is very natural way to go about. Whenever you want to do with your tagged entities, they need to be iterated somewhere. So in one system you can tag your entities with IComponentData. Then in JobComponentSystem, you can indeed utilise execution, to remove these tags and do whatever job need to be done. So this way, you do thing once. Just like one shot if needed. Barrier suites here nicely.
     
  3. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    I guess what he means is that it is probably easily optimizable as the system could just move complete chunks to the new chunks without any per entity lookups. Currently there is no way to do this more efficiently than manually remove the component from each entity individually. Could be useful in a lot of cases
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,559
    Ah I see the point. What I wonder in that case, providing you can move chunks for later use, is that you would need to ensure that entities haven't changed. I mean, no new been added, nor removed. Otherwise, could miss right batch, if I understand correctly.
     
  5. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    I don't undestand what your mean by this.
    You would have to iterate all archetypes having the component, for each iterate the chunks of this archetype and move the content to one or multiple new chunks with the new archetype. As far as I can see it can be implemented pretty easily. For reference you can look at EntityDataManager.SetArchetype. It does exactly that but for one entity.
    AllocateIntoChunk allows allocating multiple entries in a chunk at a time.
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,559
    I thought about storing current entities, with given type, so they can be reused and will, in some later frame, without iterating or disposing them.
    I may misunderstand OP concept tho.
     
  7. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,151
    Thanks for the discussion!

    julian is right on, I was hoping there might be a way to just remove the component from all entities on the World, figuring that it might be faster to do that than to remove the component on a entity by entity basis via the job.

    Because doing it this way, you could just take all chunks from the archetype that includes the component you are trying to remove, and append them to the existing chunks of another archetype (or create a new archetype if it doesn't exist).

    I will look at the EntityDataManager class, thanks for the suggestion!
     
  8. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,554
    With the current one by one removal loop I think you have 3 ways of doing it.

    1. Loop in the main thread and use EntityManager.RemoveComponent on each. If you got them via injection probably tou have to pay array copy cost on EntityArray.ToArray to prevent inject invalidation.

    2. Use ECB in the job to queue up remove commands in worker thread, and then remove for real in the main thread at barrier like you said. I think this is slower than 1. because 1. is like you are doing only the barrier part. But at more flexibility of being able to add remove command or not related to other job's logic.

    If you made a job for only putting component removal command to ECB I think 1. is faster.

    3. Use `ExclusiveEntityTransaction` and do a real component removal job in the worker thread. While in this moment you can do work in the main thread that does not touch EntityManager or it will throw error.

    If you have some idle threads and some more main thread work to do at that time I think maybe 3. could be the fastest?

    In my game I am avoiding temporary component pattern and opt for temporary entities with component instead because the only batched clean up option is DestroyEntity(ComponentGroup)
     
  9. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,151
    Thanks for the ideas. I have decided to just remove the component via an ECB for now, in the same job that is using the component to revert the values to their original values. Your option one may be the better bet, but I have a feeling they will introduce some better way to do this in the future, so I'm not going to worry about it for now. I just wanted to make sure I wasn't missing an easy way to do it with the current state of the Entities package.