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

Question Physics collisions and DestroyEntity performance

Discussion in 'Physics for ECS' started by venesectrixzero, Mar 24, 2022.

  1. venesectrixzero


    Feb 7, 2017

    I'm brand new to Unity and DOTS. I've been playing around with the systems, reading docs, and trying to understand the limits. I installed the 0.50 preview, and I'm wondering if I'm doing something wrong or if I'm at the limit already. I'm basically spawning 10k cubes in the air above a large flat surface (staggered around vertically and spread out). The "ground" is a static physics body with a Box physics shape component. All the 10k cubes are the same box physics shape and dynamic physics body. So when I test the game the cubes just fall to the ground and bounce around as expected.

    I wanted to destroy the cube (entity) when it hits the ground, so here is my collision system:

    Code (CSharp):
    1. [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    2. [UpdateAfter(typeof(StepPhysicsWorld))]
    3. [UpdateBefore(typeof(EndFramePhysicsSystem))]
    4. public partial class CollisionEventsSystem : SystemBase
    5. {
    6.     [BurstCompile]
    7.     private struct ProcessEvents : ICollisionEventsJob
    8.     {
    9.         [ReadOnly] public ComponentDataFromEntity<EnemyTag> allEnemies;
    10.         public EntityCommandBuffer ecb;
    12.         public void Execute(CollisionEvent triggerEvent)
    13.         {
    14.             if(allEnemies.HasComponent(triggerEvent.EntityA)) {
    15.                 ecb.DestroyEntity(triggerEvent.EntityA);
    16.             }
    17.         }
    18.     }
    20.     private StepPhysicsWorld stepPhysicsWorld;
    21.     private EndSimulationEntityCommandBufferSystem endECBSystem;
    22.     protected override void OnCreate()
    23.     {
    24.         stepPhysicsWorld = World.GetExistingSystem<StepPhysicsWorld>();
    25.         endECBSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    26.     }
    27.     protected override void OnStartRunning() {
    28.         this.RegisterPhysicsRuntimeSystemReadOnly();
    29.     }
    30.     protected override void OnUpdate()
    31.     {
    32.         Dependency = new ProcessEvents
    33.         {
    34.             allEnemies = GetComponentDataFromEntity<EnemyTag>(true),          
    35.             ecb = endECBSystem.CreateCommandBuffer()
    36.         }.Schedule(stepPhysicsWorld.Simulation, Dependency);
    37.         endECBSystem.AddJobHandleForProducer(Dependency);
    38.     }
    39. }
    Does this look reasonable or am I doing anything wrong here? With this system in place the main CPU thread is taking 18-20ms per frame, while without the system (just letting the cubes bounce around against the ground) it's 5-6ms per frame. I've noticed if I replace DestroyEntity with
    AddComponent then the performance is similar 5-6ms per frame.

    Is there a better way to destroy entities? Or is this about what you would expect for performance? I'm not sure if it makes a difference, but I'm instantiating the entities using this:

    Code (CSharp):
    1. blobStore = new BlobAssetStore();
    2. entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;    
    3. var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, blobStore);
    4. entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
    5. var enemy = entityManager.Instantiate(entityPrefab);
    Thanks for any insights!
  2. WildMaN


    Jan 24, 2013
    I wonder why you're checking only triggerEvent.EntityA, but anyway code looks very suboptimal.

    I hadn't tried 0.50, but from 0.6 physics perspective:
    - ICollisionEventsJob is slow single-threaded callback. Better to collect all data in native containers and process afterwards in parallel jobs
    - adding Disabled tag is way faster than DestroyEntity
    - adding tags by NativeArray override is faster than single AddComponent
    - DestroyEntity(EntityQuery) override is faster than issuing tons of single DestroyEntity calls
  3. venesectrixzero


    Feb 7, 2017
    Thanks for the feedback!

    I believe I tried some of your recommendations before, if I follow what you meant (though I didn't include that info in the post for simplicity). I stored a "destroy me" flag in a component on the entities and set that to true in the collision system. Then in a parallel job system I later used DestroyEntity. I was seeing the exact same performance drop there too.

    However, I've been doing some more testing, and I went back to the previous version of DOTS with an older version of Unity. Running similar code there in a new project I don't see this performance drop happening. Then I decided to make a new project in the latest DOTS version and Unity LTS and I don't see the performance drop happening there anymore either.

    So I don't know what kind of messed up state my project is in, but in a new project DestroyEntity is fine even using it in the suboptimal way above.
  4. WildMaN


    Jan 24, 2013
    Well, that's weird. My pet project is targeting mid-tier mobiles, so I really had to do some optimizations, including minimizing structural changes, and there were clearly performance gains. It was a while ago, but as far as I remember, queuing up AddComponent(<Entity>) calls were ~25% slower than AddComponent(NativeArray<Entity>) for instance. And destroying entities one-by-one was even slower.

    Not sure about desktop, but for mobile I had to turn on performance mode, otherwise number of active cores changed dynamically, rendering performance profiling useless. Though I don't think it should be the case for desktop, if that's your target.
  5. JosepMariaPujol


    Unity Technologies

    Jun 16, 2021