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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Best practice with 2D tile map and procedural generation

Discussion in '2D' started by marco82, Aug 7, 2015.

  1. marco82

    marco82

    Joined:
    Aug 6, 2015
    Posts:
    16
    Hello everybody! I need an advice with my project about a 2D procedural city generator.
    At the moment, I am able to procedurally build the road grid and the buildings areas on a 100x100 map.
    I am instantiating every prefab using world coordinates (so tile1 at x =0, y = 0 and tile100 at x 99, y=99) while the generator calculates grid nodes.
    I am wondering if it would be better running the generator, storing the coordinates in a bidimensional array and the using it to create all instances. I am asking it because I feel that an array with coordinates and objects stored in it would grant me a better control, but I am newbie so I am not sure if I am going to complicate things..
    Thank in advance!
     
  2. kuchaku

    kuchaku

    Joined:
    Oct 14, 2014
    Posts:
    37
    It probably depends on how many tiles you need to display on the screen. Some kind of mesh system would likely be more efficient than using prefab objects in the long run.

    Unfortunately a lot of the current pre build tile systems I've toyed with, tend to bottleneck with real time changes. For now I'd spend time taking care to separate game information (what kind of game tile is it) from rendering data (what is the graphic that is appropriate for the game tile?).

    So yes, data structures like arrays, lists, and so forth are very good. And depending on how many tiles you get on screen, an object pool of reusable contents could be doable. But it can quickly escalate and get out of control performance wise. Things that you'll want to be concerned about:

    Garbage Collection: Any solution you use, try to reuse by enabling, disabling, and modifying resuable rahter than creating and destroying over and over again. The garbage collector alone could take you out.

    Prefab Overhead: Unity prefabs take up way more head room with their transform data, than a set of meshes with the same graphics.

    Chunking: Eventually you might need to combine various tiles into larger meshes as it can batch the drawing for performance reasons. The downside is rebuilding and sorting a huge mesh can be costly in itself.

    Overall, if you're going to use individual objects, definitely pool them (I like generic lists personally, as they are resizable, but they are bit a slower).

    And while you're making your game, think of what game play purpose your tile is for, 'like oh this is a wall, this is like a floor, this might have collision information,' and intpu data like that into arrays or some kind of separate from the graphics themselves (like dirt 55 texture). This is so in the future learn better ways to render your game, you can still use the game data and just feed that data enter rendering system.

    It's on my to do list to attempt to learn to make a tile system that as efficient as possible for procedural purposes rather than static purposes. I have a lot of learning to do myself on this. Unity is planning a tilemap feature in the future, but I haven't heard any word on runtime alteration features performance. Since you're still quite early on, you can wait for that.

    But I've been getting the impression, personally, the more I've used Unity and the more I've used assets, that if I don't genuinely learn a lot of these concepts, it's going to bite me in the end. A lot of the assets are good for what they do but they aren't designed for you game and its particular quirks or requirements. And another problem is you don't learn as much by using them and at some point your knowledge base will be lacking when trying to tackle problems. If you learn something earlier, you might be prepared for later, but if you learn very little and make most of your game, and then find out one thing that requires an immense amount of prior knowledge and skill just isn't achievable with a default solution.

    Imagine if you had to spend 3 years learning how to do that one thing that would finish your game, versus having spent the last 3 years, making sure that you're learning useful skill and not just hitting magic buttons.

    Things will get better, but as it is, I don't think you could make a really ambitious 2D game in Unity without really having to dig in. 3D games have terrain systems, you have prefab sprites that are slow. 3D games have per pixel per polygon lighting. You can just stick a light into a scene. With 2d, You can't even use a projector or a light cookie or anything cause the sprite is transparent. My impression is it is endless. The sooner we learn. It takes a huge time commitment and spreading it out a bit earlier. I'd suggest that to other beginners. I feel like I've wasted some time looking for solutions that will do what I want. Where as if I spent the same amount of time, learning as much as I can about how to do various things I'd probably be a lot further ahead.

    Take care and good luck.
     
  3. marco82

    marco82

    Joined:
    Aug 6, 2015
    Posts:
    16
    Thanks a lot for your reply! Well, I think the map will be no more than 100x100 tiles..

    Building tiles will have colliders attached (and maybe damage detection). So, do you suggest to make a simple prefab and store the collision information on another data structure? Is it possible? Because I have never done it before..

    The peculiarity is that, on the top down view of the city, there will be (in my idea) hundreds of citizens walking and changing direction when hitting the collider, so I am wondering about performance issue (even if graphics will not be awesome).
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    100x100 tiles is 10,000 separate objects, which is far too many. You should use a tile system, which avoids that issue. You can make one yourself, of course, but making a good one is pretty labor-intensive. At the risk of advertising, SpriteTile was made specifically for real-time updating; to quote the most recent review on the asset store, "I'm making a top-down building / management game so being able to easily make tools for user interaction with the terrain was essential to me. The few extra classes that are added are incredibly well-thought out, providing handy data structures and functions for really intuitive manipulation of the map at runtime." There wouldn't be any issue with hundreds of objects walking and changing directions (see demo).

    You can just stick a light into a scene with 2D as well, which will use per-pixel lighting if you're so inclined. You can use projectors if you want; the sprite doesn't have to be transparent. If the default shaders don't do what you want, you can modify them.

    --Eric
     
  5. marco82

    marco82

    Joined:
    Aug 6, 2015
    Posts:
    16
    Thanks for the advice! I hope that I preserve my procedural generator and integrate it with the TileSprite package
     
  6. kuchaku

    kuchaku

    Joined:
    Oct 14, 2014
    Posts:
    37
    You can also technically use 100 by 100 prefabs to make a tile set too without pooling or anything. But because you can, doesn't mean you should. The same thing applies for me when trying to shoe horn stock 3D lights into 2D scenarios. Yeah, technically you can illuminate a sprite by choosing a material with diffuse. However:

    1. If you want dynamic shadows being casted in a flexible 2D way, light cookies aren't markable as read/write so you can't modify them to calculate your own 2D lighting field in the same way that you can with a standard texture.

    2. If you want a whole lot of lights and or shadows, it's overkill, very inefficient to calculate 3d lights in a 2d setting, compared to a a layering solution that works only on 2D. You can have at least 4 times the amount of lights all of which can be dynamic.

    3. The way 3D lights are designed to block light and create shadows (cutting off at polygonal edges) isn't as useful for 2d, where seeing partway into walls and so forth is useful.

    2d lighting has different requirements to making a convincing solution run efficiently and dynamically. This asset is a really great idea and is about as close as I've seen to a generic solution:

    https://www.assetstore.unity3d.com/en/#!/content/30953

    Some of the features it has: 2D light penetration, blockage. In 2D, you can't rotate the camera or walk behind the wall, and the graphics and game play features where that shadow is starting cast wall is extra important. It has additive lighting, soft shadowed penumbras. It's uses render textures. It's close to a generic 2D Lighting solution that you could use in almost any situation like 3D lights currently are.

    So why not just use it? Well, maybe the asset is very close to what you need, but not quite flexible enough to achieve what you want. Are there tutorials? Do you understand how it works? Are you really any closer to your goal?

    Or let's say it is working how you want, but then Unity advances and compatibility breaks. Is it realistic to believe your assets will be kept up to date for the duration of long term projects? Are you going to be stuck with a choice of fixing compatibility issues or have to stick with old Unity versions.

    In summary, I don't think there is a default, drag and drop 2D lighting solution in Unity that suffices for generic 2D needs in same way that it suffices for generic 3D needs. If you want to picture a reverse scenario of usefulness, if drag and drop 3d lights were dependent on users trying to create light in 2d screen space a 3D game. Technically, they could make things brighter or darker.

    For the time being, unless you're making very static and/or few circle based lights, I'd recommend looking into custom solutions that take advantage of the 2 dimensional aspect.
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The difference is that there aren't any circumstances in which 10,000 separate objects is desirable, whereas in many cases standard point lights and so on are fine for 2D. No sense worrying about super-fancy 2D lighting if you're not going to use it, or indeed any lighting at all (which is fairly common for 2D games). This is pretty off-topic though.

    --Eric
     
  8. marco82

    marco82

    Joined:
    Aug 6, 2015
    Posts:
    16
    Thanks everybody for all infos. Actually, light is my last problem, as I am not planning to use it for the moment.
    I purchased Rotorz tile system, and seems very good for the kind of work I need. I will also post some updates if you want.
     
  9. kuchaku

    kuchaku

    Joined:
    Oct 14, 2014
    Posts:
    37
    The only reason fancy 2D lighting is uncommon is because there was never a standardized method invented that could offer universally useful implementation for any 2D environment in any conventional engines.

    Drag and drop lighting for 3D games was included in level editors as far back as Quake and became a standard feature for all 3D engines, including Unreal and your own in Unity. In the push for 3D games, engineers focused entirely on the advancement of 3D tools, while ignoring solutions for 2D situations, and as a result 2D artists never gained the same amount of choice as 3D artists. That's why 2D lighting remains stuck back in the Snes era.

    If artists were given access to fancy lighting, you'd would see it in a lot more games. If Carmack had not pioneered drag and drop 3D lighting for his 3D artists, you'd see a lot less fancy lighting. Prior to that the Build Engine, and Doom engine used sectors, and prior to that Wolfenstein had no lighting just like 2D games.

    Advancements in engineering to created standardized 2D solutions have been neglected. It's not just Unity, it's all game engines. After 96 or so, 2D on fast current hardware was a thing of the past until indies revived it digitally on the internet. The comparison is similar to using a bunch of 3D prefabs for 2D, because 2D was removed from the industry for so long, it's kind of stuck in the 90s in favor of standardized 3D implementations.

    The majority of users don't know how to implement 1996 3D lighting, much less 2015 3D lighting. But at least it has been standardized. In the meantime, 20 years have passed. They don't know how to implement 1996 2D lighting, much less 2015 version. Engineers neglected it for 20 years, and artists and game designers lack the skills of someone like Carmack to push the envelope in providing tools. So most people make 2D games like it's 93. They don't have 20 years of advancement to utilize. It's a lot to ask for every developer to reinvent their own wheel.
     
    Last edited: Aug 7, 2015
  10. marco82

    marco82

    Joined:
    Aug 6, 2015
    Posts:
    16
    Thanks to everybody! I did it! These are the screens with the road grid procedurally generated on a 100x100 map:

    map1.JPG map2.JPG
     
    kuchaku likes this.
  11. marco82

    marco82

    Joined:
    Aug 6, 2015
    Posts:
    16
    Some small update :) Cattura.JPG