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

Question Basic questions about ECS

Discussion in 'Entity Component System' started by friesenmedien, Feb 13, 2023.

  1. friesenmedien

    friesenmedien

    Joined:
    Mar 15, 2021
    Posts:
    7
    Hey!

    So I'm pretty new to this and still trying to get my head around how to build my project.
    I am trying to create the following:

    In my "regular" Scene:
    • GameManager GameObject
    • Player GameObject (1-4 players)
    • Planet GameObject (4-20 planets)

    Then in the subscene I want to create the following entities:
    • Player Entities
    • Planet Entities
    • Unit Entities

    So player and planet objects should exist both in the normal scene as GO, and an entity in the subscene with components relevant for ECS.
    So I use ECS only to control the units (trajectories calculated etc.).
    The movement of the planets, rendering of the planets, events of the players etc. still run with Monobehaviour / GameObjects.
    According to all the tutorials on the Internet, I should now create a subscene and create all the necessary entities via baking from authoring GO.
    This works fine for me.
    e.g.:

    Code (CSharp):
    1.  
    2. class PlanetAuthoring : Monobehaviour
    3. {
    4.     // vars
    5.  
    6.     public GameObject unitPrefab;
    7. }
    8.  
    9. public class PlanetBaker : Baker<PlanetAuthoring>
    10. {
    11.     public override void Bake(PlanetAuthoring authoring)
    12.     {
    13.         // create components with authoring.vars
    14.  
    15.             AddComponent(new BasicUnitSpawner{
    16.                 UnitPrefab = GetEntity(authoring.unitPrefab)
    17.             }
    18.     }
    19. }
    20.  
    21. public struct BasicUnitSpawner : IComponentData
    22. {
    23.     public Entity UnitPrefab;
    24. }

    The cool thing is that you I get the entity with GetEntity(authoring.unitPrefab) and then I can instantiate units from it later in a system.
    But GetEntity() only works in the baker. And I don't want to manually set up my subscene to have X planets, but spawn them via GameManager after it is done generating other things.
    So I try spawning player and planet Entities in the GameManager:

    Code (CSharp):
    1.  
    2. public class GameBuilder : MonoBehaviour
    3. {
    4.     public int numberOfPlayers = 2;
    5.     public int numberOfPlanets = 4;
    6.     public List<Color> playerColors = new List<Color>();
    7.     public GameObject planetPrefab;
    8.     EntityManager entityManager;
    9.     EntityArchetype playerArchetype;
    10.  
    11.  
    12.     private void Start()
    13.     {
    14.         entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    15.         playerArchetype = entityManager.CreateArchetype(
    16.             typeof(PlayerConfiguration)
    17.             );
    18.         GeneratePlayers(numberOfPlayers);
    19.         GeneratePlanets(numberOfPlanets);
    20.     }
    21.  
    22.  
    23.     void GeneratePlayers(int numberOfPlayers)
    24.     {
    25.         for(int i = 0; i < numberOfPlayers; i++)
    26.         {
    27.             // Generate new Player Entity
    28.             Entity playerEntity = entityManager.CreateEntity(playerArchetype);
    29.             entityManager.SetComponentData(playerEntity, new PlayerConfiguration { playerColor = Color.red });
    30.             entityManager.AddSharedComponent(playerEntity, new PlayerNumber { Value = i+1 });
    31.         }
    32.     }
    33.  
    34.  
    35.     void GeneratePlanets(int numberOfPlanets)
    36.     {
    37.         for (int i = 0; i < numberOfPlanets; i++)
    38.         {
    39.             // HOW CREATE ENTITY FROM PREFAB...?
    40.         }
    41.     }
    42. }
    43.  
    Because the player is a simple Entity without transforms or child entity hierarchies, I create a player Archtype and Instatiate from it. I can see my player entities getting generated.
    So far so good.
    But how can i convert my planetPrefab Gameobject to a Entity (like I did in the baker), so that I can call entityManager.Instantiate(prefab_as_entity); ?

    And another question I have:
    The player entities, that I spawn in my GameManager are not spawned in the subscene.. see image: Entities Hierarchy.jpg

    The two at the bottom are my player entities. Shouldnt they be in my UnitsEntitiesScene (subscene) ?
    Or is this looking good so far?

    Thanks for reading all this noob stuff ^^
     
  2. friesenmedien

    friesenmedien

    Joined:
    Mar 15, 2021
    Posts:
    7
    I read that you could use something like this in previous ECS versions:

    Code (CSharp):
    1.        
    2. BlobAssetStore blobAssetStore = new BlobAssetStore();
    3. var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, blobAssetStore);
    4. entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(GOprefab, settings);
    5.  
    But I dont have GameObjectConversionUtility available in Unity.Entities?
    I dont get how I can convert a GO Prefab to an Entity in the new DOTS 1.0
     
  3. RisingSunStudios

    RisingSunStudios

    Joined:
    May 23, 2018
    Posts:
    32
    I'd also like to know this. I've seen examples using a "ConvertToEntity" component, and interfaces such as IConvertGameObjectToEntity but none of them exist after installing the latest versions of ECS
     
  4. friesenmedien

    friesenmedien

    Joined:
    Mar 15, 2021
    Posts:
    7
    I endend up using one GameObject that has all my prefabs and that then gets baked to an entity having all prefabs converted to entities:

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3.  
    4. // This GO gets converted to an entity
    5. public class EntityPrefabContainer : MonoBehaviour
    6. {
    7.     public GameObject unitPrefab;
    8.     public GameObject planetPrefab;
    9. }
    10.  
    11. // Baking the EntityPrefabContainer to an entity
    12. public class EntityPrefabContainerBaker : Baker<EntityPrefabContainer>
    13. {
    14.     public override void Bake(EntityPrefabContainer authoring)
    15.     {
    16.         AddComponent(new CommonEntityPrefabs
    17.         {
    18.             UnitPrefab = GetEntity(authoring.unitPrefab),
    19.             PlanetPrefab = GetEntity(authoring.planetPrefab)
    20.         });
    21.     }
    22. }
    23.  
    24. // Use this component to Instantiate new entities from
    25. public struct CommonEntityPrefabs : IComponentData
    26. {
    27.     public Entity UnitPrefab;
    28.     public Entity PlanetPrefab;
    29. }
    You can then instantiate new entities from Mono like this:

    Code (CSharp):
    1. // Get EntityManager first
    2. EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    3.  
    4. // Create query for entites with  "CommonEntityPrefabs" Component
    5. EntityQuery q_CommonEntityPrefabs = entityManager.CreateEntityQuery(typeof(CommonEntityPrefabs));
    6.  
    7. // Get the entity that we baked from Mono earlier
    8. Entity entityPrefabContainer;
    9. var container = q_CommonEntityPrefabs.ToEntityArray(Unity.Collections.Allocator.Temp);
    10. if (container.Length > 0){
    11.     Debug.Log("Found Prefab Container Entity");
    12.     entityPrefabContainer = container[0];
    13.     container.Dispose();
    14. }
    15.  
    16. // Get prefab
    17. Entity planetEntityPrefab = entityManager.GetComponentData<CommonEntityPrefabs>(entityPrefabContainer).PlanetPrefab;
    18.  
    19. // Spawn prefab
    20. Entity planetEntity = entityManager.Instantiate(planetEntityPrefab);
     
    Last edited: Feb 19, 2023
    RisingSunStudios likes this.