Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How do I handle this better

Discussion in 'Entity Component System' started by RoughSpaghetti3211, Jun 18, 2019.

  1. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    So Ive been dabbling in ECS for about a month, so far I really like working with it and Im ready to port my game.

    One thing Im still not sure on is how/where to create my entities. Let me explain

    For my game I have tiles , tiles are basically my units. Ive been calling them vertices since im using a subdivide algorithm to create, place and connect them to each other.

    The entire board of tiles and connections are represented by 2 struct arrays.

    Array<HexVert> & Array<HexTri>

    Code (CSharp):
    1.    
    2.      public struct HexTri
    3.     {
    4.        public int vertA;                                                        // HexA, index into the Hextile array
    5.         public int vertB;                                                       // HexB, index into the Hextile array
    6.         public int vertC;                                                       // HexC, index into the Hextile array
    7.         public int centerVertex;                                           // Center, index into the Hextile array
    8.         public int neighborsAccrossAB;                              // HexA, index into the HexTri array
    9.         public int neighborsAccrossBC;                              // HexA, index into the HexTri array
    10.         public int neighborsAccrossCA;                              // HexA, index into the HexTri array
    11.     }
    12.  
    Code (CSharp):
    1.    
    2.     public struct HexVert
    3.     {
    4.         public float positionX;                                                 // World X space of this HexTile
    5.         public float positionY;                                                 // World Y space of this HexTile
    6.         public float positionZ;                                                 // World Z space of this HexTile
    7.         public int connectedTriA;                                           //Index into the HexTri array that share this hex
    8.         public int connectedTriB;                                           //Index into the HexTri array that share this hex
    9.         public int connectedTriC;                                           //Index into the HexTri array that share this hex
    10.         public int connectedTriD;                                           //Index into the HexTri array that share this hex
    11.         public int connectedTriE;                                           //Index into the HexTri array that share this hex
    12.         public int connectedTriF;                                           //Index into the HexTri array that share this hex
    13.     }
    The tricky part is this;

    1) Each HexVert and HexTri will be an entity. Im my initial exploration I used a system to create these entities but I only need to do this once so a system felt really forced.

    I was thinking maybe it would make more sense to build this structure outside a system and pass it to a system. The way the original system was written I literary just need to pass NativeArrray<HexVert> and NativeArrray<HexTri>. instead of regular arrays. Great !! but...

    2) In the structs I have index lookups (crucial to my game) from one array into the other
    eg To access HexVert vertA in triangle = HexVert [ HexTri.vertA ] . Im my exploration I just tried replacing the int with the Entity eg (int vertA to Entity vertA). But if im not creating this structure inside a system I cant create the Entities (or its bad practice).

    3) OK so then just use a system to create the Enities from the NativeArrays :( Seems inefficient and I’m back to a system

    Any suggestion would be appreciated This has been looping min my mind for some time
     
    Last edited: Jun 18, 2019
  2. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Maybe option 3 ?
     
  3. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    use subscene and conversion utility. Look at the Megacity sample
     
  4. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Thank you for the reply, Im not sure I understand how subscene will help, could you help me understand what you mean.
     
  5. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    99% of entity creation from editor data should be doable using the ConvertToEntity workflow: https://forum.unity.com/threads/new-subscene-converttoentity-workflows.638785/

    Set up your data in the inspector then create your entities from your data so your systems can work on it.

    RE: SubScenes - they are just a way to make conversion faster. If you want to do this you need to learn and understand the ConvertToEntity workflow.
     
  6. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    954
    Is the subscene method working from code or procedural?
     
  7. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    First of all here you can read more about it:
    https://forum.unity.com/threads/new-subscene-converttoentity-workflows.638785/

    SubScenes helps you to cache entities in edit mode. This means you don't have to convert it at runtime. On the over side you have the flexibility of gameobjects in edit mode.

    And some extra... If you split your world into multiple you can easily load and unlod parts of your world (streaming) without performance impacts.
     
  8. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Both, it's just a caching system. Everything in a subscene is automatically converted to entities.
    You can control conversion with a GameObjectConversionSystem or use the IConvertGameObjectToEntity interface on Monobehaviour.

    You can read more about it here:
    https://webcache.googleusercontent....cosystem-code-tour/+&cd=5&hl=de&ct=clnk&gl=de
     
  9. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    954
    I'm using the new workflow but I'm instantiating all from code, so does this automatically go in a subscene or do I have to write additonal code for it?

    Reason I'm also asking. My terrain generation is still open and the plan was to instantiate small tiles in a grid and merge them somehow but with the subscene it seems I don't need to merge anything when I can build this cache.

    From the docs and Megacity demo I could gather that there is a SubScene monobehaviour but I don't know how to utilize this at runtime.
     
  10. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    OK so still trying to wrap my head around this workflow. Here is how im understanding it.

    Create a GameObject that holds all my data eg Array<HexVert> & Array<HexTri> and use SubScenes script to cache entities.

    Uses system as usual. Seems too simple. Am I missing somewhere here.

    EDIT : nope im way of on how this works, any help would be appreciated

    EDIT 2 : The ConvertToEntity is working so I get that concept
     
    Last edited: Jun 20, 2019
  11. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    Subscenes aren't necessary unless the process to convert your entities is really time consuming or there's so many of them that you need to isolate them in some places. Otherwise you can just use the ConvertToEntity script which will automatically convert your gameobject when you change to play mode. You do your actual conversion with a
    MonoBehaviour, IConvertGameObjectToEntity
    . I would recommend not using subscenes until you're comfortable with how the process works.

    Edit: I should also say - Subscenes are great and can really speed up your editing process since it lets you batch convert a bunch of gameobjects and inspect them in the Entity Debugger without having to switch to play mode. But I still think they should be avoided until you are comfortable with the conversion process or there is actual decent documentation for it.
     
    Last edited: Jun 20, 2019
  12. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Yes I’m using IConvertGameObjectToEntity but so far I’ve only used it on a singleton to get build settings data to used in my systems.

    In the case above if I store my two component arrays on a game object what would the Convert method look like, from what I can see it only passes a single Entity for the data conversion. I do not want one entity with 2 large arrays but instead an entity for each component in the array.

    SubScenes seem closer to what the pre ECS code was doing. Previous I had a game object with settings and a button that creates, caches and visualized the data in editor mode.

    The edit mode conversion is a really appealing way to work but I guess I would have to ask the same question, how would subScenes conversation know to create many entities from my 2 IConponent arrays instead of one entity with 2 large arrays

    Sorry about all the questions I’m trying to understand this process
     
  13. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    The subscene conversion works the exact same way ConvertToEntity works, it just runs whatever your IConvertGameObjectToEntity Convert function does. I haven't messed with it too much but I'm assuming it also runs any ConversionSystems you've set up.

    The convert function passes an EntityManager and a ComponentSystem. Using those you can create as many entities as you want. Read the thread I linked and go through the github Examples to get a better idea of how you can do it. As always the Examples have decent documentation via the readmes and can provide answers to most common questions.
     
    RoughSpaghetti3211 likes this.
  14. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Awesome thanks for the help
     
  15. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    How do I access the entity data as singleton after conversion. For example with the IConvertGameObjectToEntity the Covert method is very explicite as to where the entity data is

    Screen Shot 2019-06-02 at 1.29.43 AM.png
    and i could access by

    Code (CSharp):
    1.            //
    2.             // Get singeltion entity with build data taken from gameObject
    3.             _hexSphereBuildDataSingleton = GetSingleton<HexSphereBuildDataComponent>();
    But with subScenes it not clear to me. The examples dont explain it very well to me.
     
  16. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Spy-Shifty likes this.
  17. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Is the helloCube subScenes example meant to have any MonoBehaviours script?
     
  18. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    SubScene is just like the normal entity conversion workflow which happens with ConvertToEntity at runtime. It only caches the conversion process at editor time (pre build) and not at runtime. This means that all your gameobject are now pure entities. If your entities are in the subscene you don't need to explizit add the ConvertToEntity component to your gameobject, this is implicitly handled by the subscene context.

    For conversion you can use the IConvertGameObjectToEntity or you can create a GameObjectConversionSystem.
    Both are called when clicking on "Rebuild Entity Chache" on the SubScene combonent.

    Just use the Entity Debugger to inspect the behaviour.

    By the way, you can't use MonoBehaviour as Entity components inside of subscene. Because it only supports pure entities with no referenced types. You can only use MonoBehaviouse for converting you editor data to pure entity data.

    Hope this helps a little bit.
     
  19. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Ahhhh .. this helps a ton I will check out when I get home. Thanks so much
     
  20. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Ok Still fighting this SubScene. Here is what I have.

    A subScene in my Hierarchy

    Screen Shot 2019-06-22 at 12.15.25 AM.png

    On the child (HexSphereVisulizer) game object of my HexSphereECSSubScenes I have a MonoBehaviour ( HexSphereBuildVisualizerLiveLink ) implementing IConvertGameObjectToEntity.
    Screen Shot 2019-06-22 at 12.37.21 AM.png

    Screen Shot 2019-06-22 at 12.20.17 AM.png

    When I press "Rebuild Cache Entities " on the HexSphereECSSubScenes I can see my Entities with the correct data. (Although I see two with same data .. Entity 0 & HexSphereVisulizer) Im also setting live link on. A Debug print shows Convert() executing twice when I cache my entities.

    Screen Shot 2019-06-22 at 12.23.07 AM.png

    In my component system Im attempting to grab the entity data

    Screen Shot 2019-06-22 at 12.32.22 AM.png
    But getting this exception:

    InvalidOperationException: GetSingleton<HexSphereVisualizerComponent>() requires that exactly one HexSphereVisualizerComponent exists but there are 0.

    I can see that running the game executed HexSphereBuildVisualizerLiveLink.Convert() for a third time :(

    Any help would be awesome here , thanks
     
    Last edited: Jun 22, 2019
  21. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
  22. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    Don't think you should be using GetSingleton in OnCreateManager (in general, I don't think you should query entities at all in OnCreateManager)
     
  23. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,697
    Just wanted to update this post , moving GetSingleton/query to main thread fix the problem. Thanks again for your help