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 How to convert runtime-generated game object into entity in 1.0?

Discussion in 'Entity Component System' started by Multiainen, Feb 24, 2023.

  1. Multiainen

    Multiainen

    Joined:
    Oct 9, 2019
    Posts:
    16
    Hello,

    sorry if this is a stupid question, but I'm a complete beginner with ECS, and all of the documentation & guides I could find related to this issue were either outdated or for some reason didn't work.

    I'm making a turn-and-grid-based strategy game of sorts, which is object-oriented and in dire need of optimization. I'm already using jobs to alleviate the active operation workload, but the sheer amount of game objects is tanking performance on larger maps. The game's map generation is a minigame where the player themselves forms the terrain through a number of stages, and most of the problematic objects are part of the ensuing terrain, so we're talking generated at runtime with a generated mesh that's deformed during the map generation. As such, the most logical solution seemed to be to convert these objects into entities once map generation was finished, but I just can't get it to work.

    My first instinct was to simply create new entities with the EntityManager from a mono script for each object, and pass the relevant data to their components (in this case: position, mesh & material). I found an example of the necessary components from a previous version of ECS, using:

    Code (CSharp):
    1. EntityArchetype conversion = world.EntityManager.CreateArchetype(
    2. typeof(Translation), typeof(RenderMesh), typeof(LocalToWorld), typeof(RenderBounds)
    3. );
    While the entities were created just fine and received the data, they didn't actually render. Comparing the components to a prefab, I'd guess I'm supposed to use Render Filter Settings and Render Mesh Array instead of Render Mesh, but adding those components by their name didn't work, and I couldn't find any other way to add them.

    As an alternative, I tried instantiating a prefab with the necessary components and passing the data to that instead. In this case, however, there were two issues; firstly, using

    Code (CSharp):
    1.  
    2. UnityEngine.Material[] mats = BaseOps.AppendArray(world.EntityManager.GetSharedComponentManaged<RenderMeshArray>(sampleTile).Materials, StatRepo.staticMaterials[12]);
    3. Mesh[] meshes = BaseOps.AppendArray(world.EntityManager.GetSharedComponentManaged<RenderMeshArray>(sampleTile).Meshes, mesh);
    4. RenderMeshArray rma = new RenderMeshArray(mats, meshes);
    5. world.EntityManager.SetSharedComponentManaged(sampleTile, rma);
    6. world.EntityManager.SetSharedComponentManaged(entity, rma);
    7. world.EntityManager.AddComponent<MaterialMeshInfo>(entity);
    8. world.EntityManager.SetComponentData(entity, new MaterialMeshInfo { Mesh = counter, Material = counter + 3 });
    9. counter++;
    10.  
    ends up rendering all entities with the default non-textured pink material and throwing
    "A BatchDrawCommand was submitted with an invalid Batch, Mesh, or Material ID. BatchDrawCommand index: 1 (index in range: 1), BatchDrawRange index: 0
    This is not supported when rendering with a BatchRendererGroup (or Entities Graphics). MaterialID (0x7) MeshID (0x4) BatchID (0x2)"
    ; secondly, instantiating the prefab mesh with

    Code (CSharp):
    1. EntityQuery init = world.EntityManager.CreateEntityQuery(new ComponentType[] { typeof(PhysicsCollider) });
    2. init.TryGetSingletonEntity<PhysicsCollider>(out sampleTile);
    3. /////
    4. entity = world.EntityManager.Instantiate(sampleTile);
    does spawn the instantiated entities, as I could visually see them in the right places with the original prefab mesh when I wasn't modifying the RMA, but they disappear in the scene view and are also not visible in the entities hierarchy.

    As a third attempt I started looking into doing this with a managed component and SystemBase instead, but I expect that would run into these same two issues if nothing else. Am I just making some simple mistakes here, or are you supposed to go about doing these kinds of conversions in some completely different way?

    EDIT: Right after writing this I noticed a syntax error which changed the problem significantly, so I just updated it quickly into the original question.
     
    Last edited: Feb 24, 2023
  2. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    293
    To save you time, I suggest you go the ECS way: use bakers to prepare all the necessary components/data before the runtime. The easiest way is to build everything into a subscene and use it as a resource map to feed your map generator. After you understand this workflow, you will find ways to optimize it later.
     
  3. Simon-O

    Simon-O

    Joined:
    Jan 22, 2014
    Posts:
    51
    That's fine if you know at compile time exactly what you want to build. I'm reading data from an external source and want to instantiate a set of entities with values I have in hand.
     
  4. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    293
    I just want to be clear about your case: Do you know all the components of all entities at compile time? Or you don't know before hand the number of components for each entity and they will be composed dynamically?
     
  5. WoodsFiend

    WoodsFiend

    Joined:
    Oct 2, 2017
    Posts:
    10
    I have the exact same question. I load 3D models from an API at runtime and I need to add them to an entity. There is no way to know the components as every model is different. I have taken the hybrid approach but it doesn't work for a networked entity system like the megacity multiplayer since I am only doing it on the single client, others can't see the model.
     
  6. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    293
    Can you give an example?

    You want others to see this model too? For this case, others have to load the model too. I don't think this issue has anything to do with hybrid approach.