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. Dismiss Notice

Recursive GameObject Prefab Conversion

Discussion in 'Entity Component System' started by swejk, Mar 10, 2019.

  1. swejk

    swejk

    Joined:
    Dec 22, 2013
    Posts:
    20
    Hello,

    I would like to convert deep hierarchy of components referencing the prefabs to ecs using the new GameObjectConversion systems.

    To be specific, In the scene I have a single GameObject with GameWorldComponent referencing array of Zone GameObject Prefabs. Each Zone Prefab has an array of Unit Gameobject Prefabs. Each Unit has component referencing UnitArt GameObject Prefab etc.

    Each of GameWorld, Zone, Unit monobehaviour components declares the referenced prefabs, and Convert method to convert to ecs.

    When I run GameObjectConversionUtility.ConvertGameObjectHierarchy on the GameWorld gameObject, only zone prefabs are converted, but not the unit prefabs referenced by zone component.

    If I understand it correctly, the zone gameObject does not exist in the scene, so it is not picked up by
    DeclareReferencedPrefabs Therefore the unit prefabs are not converted.

    I am looking for correct approach to this problem.

    I tried to call GameObjectConversionSystem.AddReferencedPrefab on UnitPrefab from
    ZoneComponent Convert method, but this throws exception.
    Code (CSharp):
    1. InvalidOperationException: EntityManager.AddComponent/RemoveComponent/CreateEntity/DestroyEntity are not allowed during ForEach. Please use PostUpdateCommandBuffer to delay applying those changes until after ForEach.
    For now I am calling the GameObjectConversionUtility.ConvertGameObjectHierarchy on referenced UnitPrefabs in ZoneComponent, but I am not sure about consequences of doing it this way.

    Here is the code.

    Code (CSharp):
    1.  
    2. [System.Serializable]
    3. public struct GameWorld : ISharedComponentData
    4. {
    5.   public Entity[] ZonePrefabs;
    6. }
    7. public class GameWorldComponent : MonoBehaviour, IConvertGameObjectToEntity, IDeclareReferencedPrefabs
    8. {
    9.   public ZoneComponent[] ZonePrefabs;
    10.  
    11.   public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    12.   {
    13.     var world = new GameWorld
    14.     {
    15.       ZonePrefabs = ZonePrefabs
    16.         .Select(zoneComponent => conversionSystem.GetPrimaryEntity(zoneComponent.gameObject))
    17.         .ToArray()
    18.     };
    19.    
    20.     dstManager.AddSharedComponentData(entity, world);
    21.   }
    22.   public void DeclareReferencedPrefabs(List<GameObject> gameObjects)
    23.   {
    24.     foreach (var zoneComponent in ZonePrefabs)
    25.     {
    26.       gameObjects.Add(zoneComponent.gameObject);
    27.     }
    28.   }
    29. }
    30.   [System.Serializable]
    31. public struct Zone : ISharedComponentData
    32. {
    33.   public Entity[] UnitPrefabs;
    34. }
    35. public class ZoneComponent : MonoBehaviour, IConvertGameObjectToEntity, IDeclareReferencedPrefabs
    36. {
    37.   public UnitComponent[] UnitPrefabs;
    38.  
    39.   public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    40.   {
    41.     var zone = new Zone
    42.     {
    43.     /***************************************************************************************
    44.     * THIS WILL ONLY CREATE EMPTY ENTITY FOR UNIT, THE UNIT IS NOT CONVERTED
    45.     ***************************************************************************************/
    46.     UnitPrefabs = UnitPrefabs.Select(unit => conversionSystem.GetPrimaryEntity(unit.gameObject))
    47.         .ToArray()
    48.    
    49.     /****************************************************************************************
    50.     * THIS WORKS BUT I DONT LIKE IT
    51.     UnitPrefabs = UnitPrefabs.Select(unit =>
    52.     GameObjectConversionUtility.ConvertGameObjectHierarchy(unit.gameObject, dstManager.World))
    53.         .ToArray()
    54.      
    55.     ****************************************************************************************/
    56.     };
    57.    
    58.     dstManager.AddSharedComponentData(entity, zone);
    59.   }
    60.   public void DeclareReferencedPrefabs(List<GameObject> gameObjects)
    61.   {
    62.     foreach (var unitComponent in UnitPrefabs)
    63.     {
    64.       gameObjects.Add(unitComponent.gameObject);
    65.     }
    66.   }
    67. }
    68.  
     
  2. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    This is currently not supported. References to prefabs at this point have to come from set of objects being converted. I'll add a bug to support this.
     
    Last edited: Mar 10, 2019
    FROS7 likes this.
  3. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Additionally Zone should not be a ISharedComponentData. It can just be IComponentData. Serialization of Entity on ISharedComponentData is also not supported at the moment.
     
  4. swejk

    swejk

    Joined:
    Dec 22, 2013
    Posts:
    20
    Thanks for reply.
    For now I will use the gameobjects in scene with prefab component added manually, but would be easier for me to work with regular unity prebafs. Did not know about SCD not being supported, I will migrate to IComponentData.
     
  5. scobi

    scobi

    Unity Technologies

    Joined:
    May 14, 2014
    Posts:
    32
    An upcoming improvement will let you create a `GameObjectConversionDeclarePrefabsGroup`-grouped system, and from there you can ask the `GameObjectConversionSystem` to `DeclareReferencedPrefab()` any prefabs that aren't discoverable via `IDeclareReferencedPrefabs`.

    It's in a branch with a bunch of other improvements and fixes to conversion, which should be in master soon(ish).
     
    swejk, recursive and FROS7 like this.