Search Unity

Question Performance Help Regarding Tilemap SetTiles Outside Bounds Frame Drop

Discussion in '2D' started by QuariYune, Feb 21, 2023.

  1. QuariYune

    QuariYune

    Joined:
    Jul 1, 2021
    Posts:
    20
    Hey all,

    I've got an infinitely procedurally generated world, and I'm using a tilemap for organizing the 2d tile / voxels of the world. I've also got a chunking and culling system where only the chunks near the camera will be loaded, and loaded chunks outside that area will be unloaded. This is done by getting the tile asset and vector3int positions of each tile in the chunk, and grouping them together to use in a single SetTiles() call.

    However, I'm running into the issue where that call seems to be very expensive when positions outside of the tilemap bounds are set. When looking at the profiler, the SetTiles call takes 149ms (On a 5900X / 6800 XT) for chunks of ~4096 tiles (64 * 64). The function seems to be at Tilemap.SetTiles() > Tilemap.SetTileAssets() > ITilemap.FindAllRefreshPositions(), which takes up 78.6% of 189ms CPU time. However, settings tiles for chunks that have already been loaded then unloaded (Cleared from tilemap) seems to not have such frame hitches.

    Is there anything I'm missing about Tilemaps that is causing this frame hitch? I can't be the only one that's tried 2D procedural worlds with Tilemaps, but I can't seem to find any information about this performance hitch.

    I've though of a few suggestions that could potentially work (Haven't tried it), such as pooling pre-bounded tilemaps, and spawning from the pool as needed. I could also manage the bounds the same way the chunks are managed, so instead of every chunk triggering a hitch, a hitch only triggers after x number of new chunks. But these all add complexity a fair amount of complexity to the system.
     

    Attached Files:

  2. RobertMueller11

    RobertMueller11

    Joined:
    Feb 21, 2023
    Posts:
    1
    Hello friends. How are you all. I hope you all will be fine. I like this community so much. I really want to develop games. Is there anyone one will help me to learn to create a game
     
  3. QuariYune

    QuariYune

    Joined:
    Jul 1, 2021
    Posts:
    20
    Nevermind, I was reading the profiler incorrectly. What I was doing was calling SetTiles for each different tile asset, which is a large amount of calls rather than a single one. Combining them into a single call should improve performance.
     
  4. QuariYune

    QuariYune

    Joined:
    Jul 1, 2021
    Posts:
    20
    So, I reduced the number of calls down to just 1 per chunk (And excluded the null tiles). Unfortunately I'm still seeing the same spike in the spot, so looks like the number of calls wasn't the culprit after all
     

    Attached Files:

  5. vonchor

    vonchor

    Joined:
    Jun 30, 2009
    Posts:
    249
  6. QuariYune

    QuariYune

    Joined:
    Jul 1, 2021
    Posts:
    20
    I'm using the Tilemap.SetTiles(Vector3Int[], TileBase[]), but actually with more testing, what I noticed is that it might not be the SetTiles call but the gpu that is causing the hitch. It's strange that the profiler is showing SetTiles as being the cause of the hitch, but when I remove the SetTiles call it still hitches.
     
  7. vonchor

    vonchor

    Joined:
    Jun 30, 2009
    Posts:
    249
  8. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Hi, could you share a profiler picture where you do not get a frame hitch when setting Tiles for your loaded/unloaded chunks? This would be helpful in comparing the difference in performance!

    If the hitch is in the GPU, showing the profiler timeline for the Render Thread can shed more details on the issue here!
     
  9. QuariYune

    QuariYune

    Joined:
    Jul 1, 2021
    Posts:
    20
    Looks like the hitch was the GPU. I optimized the algorithm a bit and was able to reduce the hitch from ~200ms to ~20ms. Though unfortunately it seems like unless I spread out the work into multiple compute shaders and dispatch them at different frames, I'll always get a hitch just due to how computationally expensive it is.

    I've attached two profiler screenshots, one on the hitch and one just normally. Though I don't see where exactly the compute shader hitch is being displayed on the profiler - the rendering timeline doesn't really show any changes.
     

    Attached Files:

  10. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    I'm not too familiar with profiling for compute shaders unfortunately. Perhaps you could try setting your own ProfilerMarkers for your compute code and set the MarkerFlag.SampleGPU to see if that is now captured in the Profiler?
     
  11. incompreneur

    incompreneur

    Joined:
    Mar 24, 2023
    Posts:
    3
    It sounds like you're dealing with some pretty significant performance issues in your tilemap-based procedural world. Have you tried experimenting with different chunk sizes to see if that has any impact on the SetTiles() call? It's possible that a smaller chunk size might be more manageable, though that could require more overall chunks to be loaded at once.

    Another thing you might consider is trying to optimize the FindAllRefreshPositions() function. Are you able to dive deeper into the code for that function and see if there are any areas that can be optimized or streamlined? Even small improvements could make a big difference in the overall performance of your system.

    Pooling pre-bounded tilemaps and managing the bounds could also be viable solutions, but as you mentioned, they do add complexity to the system. Before going that route, it might be worth exploring other potential optimizations within the existing codebase.

    I hope that helps, and good luck with your project!
     
  12. Kizzyman

    Kizzyman

    Joined:
    Apr 12, 2016
    Posts:
    1
    I'm having this exact same issue, procedural 2d world with tilemaps, and setting tiles with Tilemap.SetTiles(). Did you have any luck finding a solution?