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

Discussion Without meshing, is there any reason not to have one Entity per Tile/Voxel?

Discussion in 'Entity Component System' started by frankfringe, Sep 28, 2023.

  1. frankfringe

    frankfringe

    Joined:
    Feb 9, 2019
    Posts:
    83
    Hey, I have read through the old discussions in the forum on voxel/tile worlds (there are plenty haha).

    I understand that when building a mesh, you'd want it in chunks.

    But now if it is just a flat tile-world, but with quite some simulation data per-tile (humidity, etc.), is there any argument against having them in ECS? The only reason for chunks I see is having good spacial queries.

    But, if I have one entity per tile, I can also have good spacial queries, by giving them a shared component data to all map them to the same archetypeChunk. Then I have another simple array which I can use to get Entity Id from position, and voila, I have spacial queries that are as cheap as if I would have chunked the data (except for the dereferencing the entity id instead of having an integer directly).

    Back then @tertle (sorry for ping), was saying in many threads that he thinks the whole thing should be out of the ECS in general, but I am not sure if this was because of the meshing or applies in more generality.

    I think having entities-per-tile is easier to code, since I don't have the chunk-abstraction (the chunks are handled as archetypeChunks for me by the ECS), and I just don't see which pitfalls this could have, except if the tile data gets so big that the 64kb per archetypeChunk do not hold many tiles (but then I could split it up probably).
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,574
    Tilels as vertices count will contribute to gpu load. Depending of course how big map is and how many vertices, and depending on hardware target.

    If you have let's say 100x 100 tiles that is 10k tiles, no big deal. But if you have 100k tiles, now iterating through them to compute things, may start become visible on CPU. But if you manage to have good optimisation that should be fine.

    Either way, to avoid speculations, you need to stress test your use case.

    Your major aspect will be culling, depending how is implemented. Latest Unity graphics may be sufficient. But haven't tested it, so here is area for you to explore.

    But wonder, if implementing DrawMeshInstantiation may be better solution. At least it was while go.

    Either way, you don't need all let's say 100k meshes, if you can cull tiles and reuse them in different place of the map, which is visible.
     
    Last edited: Sep 29, 2023
    apkdev likes this.
  3. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    There are a lot of trade off to consider.

    One entity per voxel/tile may be easier to program but you will have a biger memory footprint since each will hold its positional data. If you go with a chunked approach only the chunk will have it and the tiles will be relative to that.
    That will imply a calculation cost of each vowel position. It may impact vectorization of your code.
    You also have to consider the 128 entity per chunk limit because of enabled disabled components feature.

    I'm sure there are many more considerations I'm missing cause I never did try to make something like that but that what my first approach would be.

    Go first with a 1 entity per tile POC.
    If from that you already start seeing things like low chunk usage (can't even fit 128 entities per chunk) or that all your systems are just iterating over all entities without much random access (or those are limited to close neighbors).
    Then a chunked approach might be better.
    For me the biggest complexity of the chunked approach is the chunk boundaries when you have to accès data from 2 neighboring tiles in different chunks. But once you figure that logic out it should be fine.

    Keep in mind that if you go with the 1entity 1tile approach you will essentially end up in that situation for every single tile...
     
  4. frankfringe

    frankfringe

    Joined:
    Feb 9, 2019
    Posts:
    83
    Thanks for the answer! I don't fully understand how this relates to chunked or not chunked though. Iterating over the tiles is something that I have to do anyways, no matter if in my own chunks or archetype chunks.

    And also meshing I could theoretically do independently of where the tile data is saved
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,574
    The chunked approach allows to group entities, and potentially share same component property on the chunk.

    Here is a thing, I don't think you need to calculate many neighbour entities anyway. Unless you run some flood algorithms. Or you run some micro economy/ecology simulation, which affects neighbour tiles and it may propagate across other neearby chunks. Just like A* does.

    I suppose navigation, if you got many characters, or A, then you start iterate over neighbours entities. But depending how far you need to move.

    If game is more like Civ series, which is turn based, I wouldn't stress too much about it

    If is real time however, you should more closely tes performance.

    So regarding chunks, if you do lots of neighbours checks, which is random ecces of entities, than you won't gain much of hat approach. However, assuming not all entities need be processed every time, you may be fine as well.
     
  6. frankfringe

    frankfringe

    Joined:
    Feb 9, 2019
    Posts:
    83
    Hello, thanks for the answer too! Also nice videos by the way haha.

    So chunk utilisation is my main concern. But I think 128 tiles per chunk would be totally fine.
    And in 16kb I would have space for

    16kb / (32 bit * 128) = 32

    32 float32 variables. Minutes entity overhead and position overhead maybe, 30 or 29. I'm quite sure that's more than enough for my small game.

    I don't think chunking stuff is that complicated, it just seems as if I am reimplementing something that ECS has already implemented and I don't understand the benefits of it.

    The neighborhood updates are also not what bothers me the most (I could just have a fixed array per chunks that has all chunk and tile Ids for a chunk with sidelength chunk_sidelength+1, so I would only need to do lookups in this read only never changing array).

    It's more that just getting tile and it's components, or iterrating over it seems nicer than always getting the chunk first, then getting it's buffers and finding the right tile. Or iterating over all chunks and then having another for loop to iterate over all tiles. All of these things (for example going from global entity id to (archetype chunk id + id archetype in chunk) are already implemented in ecs. I just don't really see a reason but I am scared of shooting myself in the foot since the general tone on these forums (albeit quite a while ago), seemed to be to go for self-managed chunks.

    But maybe the actual stuff people meant was that the meshes should be generated in chunks, not per voxel (in my case tile). That makes total sense to me, but is a matter that's unrelated to how I store tile simulation data
     
  7. frankfringe

    frankfringe

    Joined:
    Feb 9, 2019
    Posts:
    83
    I will do neighborhood checks a lot for the simulation, but the simulation won't be every frame. The game itself is real time but the simulation does not have to be. Flood and ecology are good examples of why I'll need neighborhood checks.

    And I do think chunks are precisely good in this case and gain you a lot, since they make spacial queries be less of random access (the neighboring tiles are already loaded).

    What I am saying is that I think one can use archetype chunks instead of managing your own chunks for this purpose.