Search Unity

Destroy GameObject after initialization

Discussion in 'Entity Component System' started by MikeMarcin, May 28, 2018.

  1. MikeMarcin

    MikeMarcin

    Joined:
    May 15, 2012
    Posts:
    17
    I'm using many GameObjectEntities with CopyInitialTransformFromGameObject to specify markers in the world (spawn points etc). Combined with ComponentDataWrapper this recaptures much of the non-ECS level design workflow I'm used to.

    Once my marker entities are created and their transform has been copied I no longer need the GameObject. I only need the entity and it seems wasteful to keep the GameObject around. Unfortunately the only way I can see to accomplish this right now is with some gross reflection hacks.

    But it does work as expected; the GameObjects are gone, the entities remain, and the other systems operate correctly.

    Is there a better way to do this? If not, can this be supported more directly?

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Entities;
    3. using Unity.Collections;
    4.  
    5. public struct DestroyGameObjectAfterInit : IComponentData { }
    6.  
    7. public class DestroyGameObjectAfterInitComponent : ComponentDataWrapper<DestroyGameObjectAfterInit> { }
    8.  
    9.  
    10. [UpdateAfter(typeof(Unity.Transforms.CopyTransformToGameObjectSystem))]
    11. public class DestroyGameObjectAfterInitSystem : ComponentSystem
    12. {
    13.     public struct Group
    14.     {
    15.         public int Length;
    16.         public GameObjectArray gameObjects;
    17.         [ReadOnly]
    18.         public ComponentDataArray<DestroyGameObjectAfterInit> destroyGameObjectAfterInit;
    19.     }
    20.  
    21.     [Inject]
    22.     public Group group;
    23.     private System.Reflection.MethodInfo entityPropertySetter;
    24.  
    25.     public DestroyGameObjectAfterInitSystem()
    26.     {
    27.         var entityProperty = typeof(GameObjectEntity).GetProperty("Entity");
    28.         entityProperty.DeclaringType.GetProperty("Entity");
    29.         entityPropertySetter = entityProperty.GetSetMethod(true);
    30.     }
    31.  
    32.     protected override void OnUpdate()
    33.     {
    34.         var argsNullEntity = new object[] { null };
    35.  
    36.         for (int i = 0; i != group.Length; ++i)
    37.         {
    38.             var go = group.gameObjects[i];
    39.             var goe = go.GetComponent<GameObjectEntity>();
    40.             var entity = goe.Entity;
    41.             entityPropertySetter.Invoke(goe, argsNullEntity);
    42.            
    43.             GameObject.Destroy(go);
    44.  
    45.             PostUpdateCommands.RemoveComponent<DestroyGameObjectAfterInit>(entity);
    46.         }
    47.     }
    48. }
    49.  
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    How about using `ComponentArray<CopyInitialTransformFromGameObject>` instead of `ComponentDataArray<DestroyGameObjectAfterInit>` as your struct component group? That way you get all game objects which has its value copied right?
     
  3. MikeMarcin

    MikeMarcin

    Joined:
    May 15, 2012
    Posts:
    17
    IIRC the CopyTransformToGameObjectSystem removes the CopyInitialTransformFromGameObject component after it runs.
     
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    I took a look at `CopyInitialTransformFromGameObjectSystem.cs`, it did remove that component but it was scheduled on the command buffer that ties to an `EndFrameBarrier`

    So in that same frame I think you still have a chance to inject the component and use them.
     
  5. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    I personally think I prefer @MikeMarcin 's solution. I am however doubting whether the need for a system like this outweighs the performance impact of it. As long as these markers aren't interacted with at a later stage just leave them there until you notice a significant drop in performance from having a lot of them hanging around. If however you're looking for a way to setup a scene using a bunch of GameObjects, but then moving them over to Entities and destroying the original objects yields enough of a performance gain it should be a good start. The reflection code is a bit scary, but I think once Unity can provide a way of interacting with ECS from the inspector.