Search Unity

Pure ECS rendering

Discussion in 'Graphics for ECS' started by iiziziz, May 3, 2020.

  1. iiziziz

    iiziziz

    Joined:
    Mar 20, 2014
    Posts:
    11
    Hi,

    I'm trying to render my first pure ECS entity.
    I found in a lot of posts that
    RenderMesh
    and
    LocalToWorld
    are the components needed to see the entity rendered.

    But with the following code, nothing renders.
    Code (CSharp):
    1. public class BoardGenerator : MonoBehaviour
    2.     {
    3.         public List<int2> TileCoordinates;
    4.  
    5.         public Mesh Mesh;
    6.         public Material Material;
    7.  
    8.         public float Padding;
    9.  
    10.         private EntityManager _entityManager;
    11.         private EntityArchetype _tileArchetype;
    12.  
    13.         private List<TileComponent> _tiles;
    14.  
    15.         private float _meshWidth;
    16.         private float _meshHeight;
    17.  
    18.         private RenderMesh _renderMesh;
    19.  
    20.         void Start()
    21.         {
    22.             _entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    23.  
    24.             _tileArchetype = _entityManager.CreateArchetype(
    25.                 ComponentType.ReadWrite<TileComponent>(),
    26.                 ComponentType.ReadWrite<RenderMesh>(),
    27.                 ComponentType.ReadWrite<LocalToWorld>(),
    28.                 ComponentType.ReadWrite<Translation>(),
    29.                 ComponentType.ReadWrite<RenderBounds>());
    30.  
    31.             var meshCenter = Mesh.bounds.center;
    32.  
    33.             _tiles = new List<TileComponent>();
    34.  
    35.             _meshWidth = Math.Abs(Mesh.bounds.max.x) - Math.Abs(meshCenter.x) + Padding;
    36.             _meshHeight = Math.Abs(Mesh.bounds.max.y) - Math.Abs(meshCenter.y) + Padding;
    37.  
    38.             _renderMesh = new RenderMesh
    39.             {
    40.                 material = Material,
    41.                 mesh = Mesh,
    42.                 subMesh = 0,
    43.                 castShadows = ShadowCastingMode.On,
    44.                 receiveShadows = true
    45.             };
    46.  
    47.             InitializeBoard();
    48.         }
    49.  
    50.         private void InitializeBoard()
    51.         {
    52.             foreach (var tileCoordinate in TileCoordinates)
    53.             {
    54.                 CreateTile(tileCoordinate.x, tileCoordinate.y);
    55.             }
    56.         }
    57.  
    58.         private void CreateTile(int tileCoordinateX, int tileCoordinateY)
    59.         {
    60.             var tile = _entityManager.CreateEntity(_tileArchetype);
    61.  
    62.             _entityManager.SetSharedComponentData(tile, _renderMesh);
    63.  
    64.             _entityManager.SetComponentData(tile, new RenderBounds
    65.             {
    66.                 Value = new AABB
    67.                 {
    68.                     Center = Mesh.bounds.center,
    69.                     Extents = Mesh.bounds.extents
    70.                 }
    71.             });
    72.  
    73.             _entityManager.SetComponentData(tile, new Translation
    74.             {
    75.                 Value = new float3(
    76.                     tileCoordinateY * 0.5f * _meshWidth + tileCoordinateX * _meshWidth,
    77.                     0,
    78.                     tileCoordinateY * 0.75f * _meshHeight)
    79.             });
    80.  
    81.             _entityManager.SetComponentData(tile, new LocalToWorld
    82.             {
    83.                 Value = new float4x4(
    84.                     quaternion.identity,
    85.                     new float3(
    86.                         tileCoordinateY * 0.5f * _meshWidth + tileCoordinateX * _meshWidth,
    87.                         0,
    88.                         tileCoordinateY * 0.75f * _meshHeight))
    89.             });
    90.  
    91.             var tileComponent = new TileComponent
    92.             {
    93.                 XCoordinate = tileCoordinateX,
    94.                 YCoodrinate = tileCoordinateY
    95.             };
    96.  
    97.             _entityManager.SetComponentData(tile, tileComponent);
    98.  
    99.             _tiles.Add(tileComponent);
    100.         }
    101.     }
    What did I missunderstood ?
     
  2. jasons-novaleaf

    jasons-novaleaf

    Joined:
    Sep 13, 2012
    Posts:
    181
    Here is a great tutorial on how to this:
     
  3. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    The "intended" way to create entities now is to use the conversion workflow. Any time you see some tutorial or youtube video talk about "Pure ECS" - including that one - they're probably working off outdated information or they just haven't read up on how the conversion system works.

    Anyways, you should clone the github samples and try to learn from those (the readmes are detailed and up to date) and the manual. Most other info you find out there is probably out of date.
     
  4. jasons-novaleaf

    jasons-novaleaf

    Joined:
    Sep 13, 2012
    Posts:
    181
    @Sarkahn From my (very limited) understanding, the conversion workflow is basically "use the editor to create GameObjects and then magically convert to DOTS".

    I don't want to do that. I want to create entities from code. I was able to do the above video in Unity 2020.2 and everything worked. If there is a better way of doing so via DOTS, please let me know. I'm new to Unity and DOTS and generally would like to do things in code not via the editor. (I'm interested in procedurally generated/authored content)
     
  5. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    I hear you - literally everything I've done in dots has been procedurally generated! But there's really nothing "magic" about conversion - it's complicated for sure but the documentation is getting better. And even for procedural generation I use the authoring workflow to set up prefabs and editor tools, it's actually very useful.

    As an example - I have a couple of different "monsters" I spawn in my map - a goblin and an orc. Because it's ECS there's obviously no "Goblin" or "Orc" class, they're just entities comprised of components, but I can still set them up entirely in a prefab:
    Unity_G5sBJAEyEf.png

    So I have a nice list of easily tweakable components for my prefabs. Then in my map authoring script I just reference the prefab:
    Unity_YHddCxn4HJ.png

    Then when the map is converting it can convert the prefabs to their entity representations via the
    IDeclareReferencedPrefabs
    interface. And I can spawn my monsters procedurally in the code. And just to be clear - at runtime I am spawning the entity representation of my prefabs, there are no gameobjects at runtime.

    By using the conversion workflow you can make it really easy to set up and tweak the elements of your procedural generation completely through the editor which is incredibly useful for fast development and experimentation. Hopefully that all makes sense!
     
    Last edited: Jan 6, 2021
    lclemens, apkdev, MNNoxMortem and 6 others like this.
  6. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,708
    It’s so good to see how people work , thanks for sharing this.
     
    MNNoxMortem, Krajca and Sarkahn like this.
  7. jasons-novaleaf

    jasons-novaleaf

    Joined:
    Sep 13, 2012
    Posts:
    181
    Thanks Sarkahn, I definitely can believe that using the conversion workflow is the best way to prototype / iterate.

    I will give it a try.
     
    Sarkahn likes this.
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    Myself I generate most stuff procedurally.
    However, I use GO conversion work flow, to get besics meshes into entity format as prefabs.
    This is so, it is easier to manipulate and test materials and shader on GO via inspector, between runtimes.
    Then I create more complex DOTS entities prefabs if needed, by adding required components via code.

    So for example, I can convert base cube into entity prefab. Then have derived multiple prefabs from that, sharing same mesh, but having different functionality, defined by corresponding entity components.
     
  9. keeponshading

    keeponshading

    Joined:
    Sep 6, 2018
    Posts:
    937

    Sorry. This is an great series with 9 videos.

    1) Unity Dots: Creating an Enity,
    where he explains base principles and refers at the beginning to the next video....

    2) Unity Dots: Conversion Workflow

    ...

    Judging a video without having seen it and claiming probabiltys "they're probably working off outdated information" helps noone.
    Just saying.
     
    Last edited: Jan 18, 2021
  10. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    I did skim the video, and saw that in it he's calling into the DefaultGameObjectInjectionWorld from a Monobehaviour to manually create entities in code. That's how I reached the conclusion that it was not a great intro to entities, a conclusion I stand by.

    Anyways, this is a screenshot from the end of that "Conversion Workflow" video:

    chrome_RhFHbW8Zv1.png

    This will technically work (for now) but manually calling into conversion at runtime is going to be deprecated so in my opinion it has no place in a tutorial. The intended way to do what he's doing above would be to write an IConvertGameObjectToEntityScript with IDeclareReferencedPrefabs. That defines the conversion in a way that's future proof and can be used with subscenes or with the ConvertToEntity script.

    And for the record saying someone is working from outdated information isn't a criticism on them - if anything it's Unity's fault for giving us almost no documentation on conversion until very recently.
     
    Last edited: Jan 18, 2021
    charleshendry and Lukas_Kastern like this.
  11. keeponshading

    keeponshading

    Joined:
    Sep 6, 2018
    Posts:
    937
    Just found the series very helpful.
    Subscens and further method follow in video 3 and 4.

    It s a little hard to get because videos don t have numbers.
    But in the right order there is a pretty good cover....

    1. Unity DOTS: Creating an Entity https://youtu.be/H-goqMxN0Bc
    2. Unity DOTS: Conversion Workflow https://youtu.be/wsohegMV6fk
    3. Unity DOTS: Components and Systems https://youtu.be/HdJHk0moJ7c
    4. Unity DOTS: C# Job System https://youtu.be/E8VNVTsRE4I
    5. Unity DOTS: System Base
      "

    1. DOTS Gameplay: Basic Player Input and Movement: https://youtu.be/lFl2SMfhvoA
    2. DOTS Gameplay: Tags: https://youtu.be/6iNXkR3ukD0
    3. DOTS Gameplay: ComponentDataFromEntity: https://youtu.be/UUCv2nDAKg4
    4. DOTS Gameplay: EntityQuery https://youtu.be/IuoKWupJ6zo
    5. DOTS Gameplay: Trigger Events https://youtu.be/jga3nj_Ott4
    6. DOTS Gameplay: Collision Events




     
    Last edited: Jan 18, 2021
    Sarkahn likes this.
  12. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    Those later videos definitely look much better in terms of what I'd expect "normal" ECS code to look like IE: Not awkwardly calling into DefaultGameObjectInjectionWorld from inside a monobehaviour to try and do everything. Again I only skimmed them but from from the SystemBase video on it seems like it would be a fantastic intro to ECS!