Search Unity

Question Looking for guidance on creating Tillemaps and Tiles via code

Discussion in '2D' started by jtsmith1287, May 10, 2023.

  1. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Ultimately, I'm just learning the 2D pipeline as of hours ago. I thought it would be a fun exercise to make a dwarf fortress clone (lol... not really but just the map and play area with some proc gen stuff).

    Initially I just created quads, but very quickly a map that was 100x100 tiles (which is really small for what I'm going for) crawled to a halt for performance. I will need multiple layers (elevation) of probably 500x500 tiles to really emulate what DF has going on for the playable map. This would be like .02 FPS based on what I'm seeing for performance so with 5 layers of 100x100 quads (each with their own renderer for holding an image). It is now obvious this is the incorrect approach.

    That's the context. So I learned about tilemaps and chunking. Sounds perfect and will probably be what I need to scale. Except the unity documentation is lacking and youtube videos seems to be behind on the version. You can't just make a "Tile" anymore with the create asset menu? I've tried creating rules tiles and I've tried creating a UnityEngine.Tilemaps.Tile in code to just fill out properties manually.

    Nothing is working. And by working, I mean nothing is creating me a Tile that I can then assign to the tilemap with SetTile(). I want to create a "canvas" of top down terrain, then batch draw it all as 1 image using a tilemap per layer so things perform faster. If I want to have 32 layers (16 above, 16 below) I assume 32 renderers will perform happily. That's all speculation though as I can't test haha. But I also need to be able to change that tile image at any time and I think the Tilemap Grid system will be awesome.

    Anyone able to help? I've been farting around with this for the majority of the day and I think I've run out of things to try.

    Right now I have a single 16px by 16px sprite called "grass" and I just want to spawn about 5 tilemaps, each @500x500 of these grass sprites and maintain performance. That'll be all I need to take off running with the rest of the vision.

    EDIT: Unity version is the latest. I just downloaded it last night. 2021.3.24f1 Personal.
    EDIT AGAIN: I have both the 2D Tilemap Editor and 2D Tilemap Extras installed.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    The problem with your approach is unlikely just the choice of sprite vs Tilemap vs Quad.

    The problem is far more likely to do with simply trying to make the entire world at once.

    Only small games can do that.

    Most significant-scale games make only what you see at any given instant. You might have a massive 5000x5000 world but in
    df
    you would only likely see 80x50 or whatever the sub-screen area is.

    Sounds like maybe you have compilation errors?? A
    Tile
    is just derived from a
    TileBase
    which is derived from a ScriptableObject, so I am pretty sure you can make as many of them in code as you want with
    ScriptableObject.CreateInstance<Tile>();
     
  3. karderos

    karderos

    Joined:
    Mar 28, 2023
    Posts:
    376
    wierd that the tile creation is gone, lucky that I have tiles from previous version and just duplicate them
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,485
    Follow: https://docs.unity3d.com/Manual/Tilemap-CreatingTiles.html

    After you drag a sprite into the tile-palette, you're asked to create a name for the tile-asset to be stored and there you go. You can modify the asset, copy/delete it etc. You can paint with this or use SetTile with this.

    To use SetTile, create a script with a public TileBase field and you can drag the asset to the script field in the inspector and use it in the script.

    More info here: https://forum.unity.com/threads/how-do-i-use-settile-with-a-tile-asset.988079/

    Addressable Assets: https://docs.unity3d.com/Packages/c...6/manual/AddressableAssetsGettingStarted.html
     
  5. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    I believe I've got it.

    32 layers, each @ 256*256 tiles running at 170fps (in the editor, so rendering 2 windows simultaneously). Each terrain layer is its own tilemap. And I simulate a grid by setting the transform's Z to the layer's elevation. I wasn't doing this before and all 32 layers were competing to render I think. I couldn't get over 50fps previously. Once I staggered the transforms the fps went through the roof, even with all 32*256*256 tiles active (2,097,152).

    Actually, out of curiosity, I just closed my Scene View window and left open only the game view and FPS rocketed to 450. That's exciting because that means I could easily double the map size and have no impact to framerate.

    As I'm typing this I'm realizing things. My scene view is set to 3D mode and I have the camera angled so I can see all the layers, and the performance drops to 30fps. As soon as I pop it into 2D mode performance bounces back. So the culling is doing its job well.

    Just tested 64 layers of 256. Takes about 5 seconds to generate the tiles (it'll be WAY more with procgen involved, so this will definitely not be the final height) and then I get about 150fps. If I closed the scene view it jumps to 250. That's with 64 individual tilemaps each with active layers of 256 tiles (culled).

    Cool. Woot. Success. It's a start. Now I can feel comfortable about moving forward with this idea.

    It may be overkill, but I'm considering ECS for handling the world simulation (creatures, building, weather, etc). It might be overkill, but the thing I hear about dwarf fortress is it gets bogged down with 200+ creatures being simulated, and that's with 20 years of development. It should be a fun learning time. I don't know anything about ECS architecture. lol.
     
    Kurt-Dekker likes this.
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,485
    Well also consider that ECS is the data-management portion. A more old-school but equally powerful approach is to manage the data yourself in a well laid out way and use parallel jobs to process it. Or at least do experiments with that. ECS just tries to keep data layout efficient but if used incorrectly, isn't always good and can even be worse in some cases.

    Bear in mind that whilst the DOTS physics uses ECS as its data-store, 95% of the processing is just querying that via job systems and execting those jobs.

    I only state this as you can experiment with jobs and well laid out data and get a huge performance boost where you need it without having to use a drastically different technology. :)
     
  7. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Parallel threads? Or something like coroutines? I see coroutines as sort of batching big jobs, or extending a process cleanly. Not sure if that's what you are referring to by parallel jobs though.

    Honestly I've never tried to tackle a project that contains as much data as this likely will. And any of it will need to talk to any other at any given time. I haven't really taken too long to think about it yet as I was going to look into dots and ecs tutorials once I got my map generating the way I want. But now that you mention it i'm going, "Oh shoot... how do I do this?" lol.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,485
    Not coroutines, they just run on the main thread and don't speed-up anything.

    I mean using the Job System to run code not only execute code off the main-thread but utilising lots/all the cores on the device.

    https://docs.unity3d.com/Manual/JobSystemCreatingJobs.html

    I would search for "Unity Job System Tutorial". You should find many easy to understand things to get your started. Start with adding up a long list of values (a million values) then try doing that in parallel etc. You'll soon get the hang of it and you won't need to understand ECS or any of those other technologies which in themselves can be a little daunting. Stick with MonoBehaviour and use Jobs to do any heavy lifting. :)

    The trick to using Jobs is getting used to using the Native Collections (NativeArray, NativeList etc) and not managed collections (List<T>, Array<T> etc). Beyond that, it's pretty easy once you get used to what's going on.

    Here's one of many: