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

What's your approach to generate tilemap collider data?

Discussion in '2D' started by Digika, Mar 28, 2021.

  1. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    As far as I can see there a few ways:

    BAD:
    - using default Tilemap collider. This kills performance

    BAD but different bad:
    - using Composite + Tilemap colliders pair. Better performance wise but you never can get it right and neither of the options are helpful, especially if your tiles artwork has bumps and protrusions (rocks pop out or weed, etc)

    BAD but different bad #2:
    - sprite physics shape through Sprite editor. Dont even get me started on how awful whole thing is.

    GOOD but also BAD:
    - defining collider manually, using either polygon, boxes or edge. This kills your tendrils and your time.

    ACCEPTABLE, but mixed:
    - some people use extra tileset that contains only straight shapes with acute edges, basically boxes and "true" triangles. This way Composite + Tilemap colliders pair generates very even final collider. However, this doubles your workflow essentially. You also later need to pre-process extra data, remove fake tilemap and cook colliders, preferably into solid polygon one. This also requires custom workflow and tools (i mean, you dont have to, but then you no better than random asset flip).

    GOOD but very hard:
    - write your own collider generator based either on sprites or Composite collider output. This has a high entry price (you need to be math genius or you need to pay one for effective and reuseable solution) but low cost of maintenance afterwards.

    "CORRECT" one:
    - "lmao, Unity's free stuff always junk, just use Tiled, dummy"
     
    Last edited: Mar 28, 2021
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,512
    Why does this kill performance?

    This makes no sense because you're saying this is better performance but it involves more work. It has to take the collision shapes from the TilemapCollider2D and convert them to whatever you select (Outline/Polygon)

    I'm not following any specifics in your post TBH and this statement just seems like you came here to rant without needing any help.
     
    MousePods and m_vishuu like this.
  3. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    Because default Tilemap collider generates collider for EACH tile individually? This is common knowledge. Why yes, on something like core i7 11-700k/GTX3080 you wont see an issue but when you made another 2D pixel game that barely more complex than Mario on NES and it puts on its knees PC from 2010 then you have a problem.

    Yes, that it why it is better performance because you now have one collider, merged, not a few hundred of individual (or however much tiles do you have in your scene)

    It was a joke.

    I didnt ask for help, I asked for some opinions and what approaches other people took in this endeavor. Now, if you actually did your research you'd know that the answer is obvious - most people (read: "successful well-know projects, and not just on Unity") just use Tiled (or similar 3d party tools) instead of Unity stuff, hence the joke mentioned before. Granted, it wasnt really an elegant one, but being an ESL I am - I think I can afford it.
     
    Last edited: Mar 28, 2021
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,512
    That's done regardless and I should know, I implemented everything in TilemapCollider2D and CompositeCollider2D. This has to happen first because that is then passed on to the CompositeCollider2D.

    If you have 10 or 10,000 shapes, there is no overhead of that when they don't change. The physics system doesn't iterate all them per-step or anything. The fact that the composite can reduce the number of shapes doesn't change the performance after creation at all. Changing a composite means it ALL has to be recreated. Changing a Tilemap means only that tiles shapes are recreated. It's a balancing act in terms of whether you use composite and how many separate tilemaps you use. Note that the physics system doesn't see "Unity Colliders", it sees physics shapes; this is an important distinction. Take a look at the ShapeCount on any collider (tilemap, composite) as that'll show you how many shapes are created. More shapes does not equal worse performance. The main difference is memory overhead.

    Asking for opinion is the help I'm referring to. If Tiled works for you then that's fine but a post where I don't understand the statements being made is why I'm querying stuff.
     
  5. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    Yes, it does, you dont see it ona decent PC but try an older on or weak laptop and do profiling and you will see higher memory usage and, depending how much dynamic objects that will collider with the env, you have - higher to some degree CPU load. Does not matter how big it is - If you can take that load off to free more frame time for logic and your data - you should do that.
    Also, if you read any docs or watch any talks from Unity itself on Tilemap - this is the first thing they recommend. There are probably your own words in one of these talks stating the same.
    There is no reason to take simple jokes personally.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,512
    I'll leave you to your opinion but I feel you're mixing things up here. I'm not sure if you're talking about creation cost of the shapes or overhead after they've been created (which is zero) as you're being very general. Reducing the complexity of shapes that you're in contact with will help but not to the degree you seem to be indicating. Honestly, at this point I'm not sure it's going anywhere and it doesn't seem I can help you; I might even be annoying you, not sure.

    I'm not sure why you think I'm taking anything personally. I thought this was something you were looking into. I didn't see the joke myself but yeah, just trying to figure out how I can help you.
     
  7. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    You are not annoying me, I just wasnt interested in recommended by Unity solutions, I just wanted to know some general info on the approach other people took and reasons why. Well, anyway, now this thread can be closed.
     
  8. rarac

    rarac

    Joined:
    Feb 14, 2021
    Posts:
    570
    create a byte array of 0s for empty space, 1s for solid blocks, use math to compare your position with the terrain array. Crawl your tilemap to fill the byte array with 0s or 1s. Yes, this doesnt use any of the built in unity collisions
     
  9. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    That wont work for partially filled tiles, say, diagonally or uneven diagonally or may be just few pixels of the tile occupy a little bit of space in the grid block. You cant really mark it as 1 it is not solid.
     
  10. rarac

    rarac

    Joined:
    Feb 14, 2021
    Posts:
    570
    for half filled you can mark it as 2, quarter filled as 3. Basically you have 255 degrees of fullness in a byte

    if 255 variations is not enough you can go further and make a ushort array then youll have 65k some variations available, if its still not enough you can make it a uint and you will have 2billion

    by the way this is how terrain and collisions are done in minecraft so it works for infinite worlds
     
    Last edited: Mar 28, 2021
    CyRaid likes this.
  11. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    I see, so this is where memes like "it takes 10k$ PC to run minecraft" came from... ;)
    That being said, minecratf is developed in mind with dynamic world structure. Suggested by you approach is not really relevant for your basic pixel games with non-dynamic (or little to none) physics/collision destruction and not gonna be very relevant performance-wise as well, in my opinion. Plus you have to basically invent whole system of handling all this stuff, handle some moving objects even if rarely, etc.
     
  12. rarac

    rarac

    Joined:
    Feb 14, 2021
    Posts:
    570
    ah, you think you will have a game with better performance than minecraft, cool story bro xd
     
  13. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    I never said that, but if you unironically think that every basic pixel platformer should have Minecraft physics system I think we might have a problem here of 2 very different priority and rationality systems.
     
  14. rarac

    rarac

    Joined:
    Feb 14, 2021
    Posts:
    570
    you might be using the wrong platform for development I think, the basic things you want out of the box do not exist in unity, you just need to browse these forums to see that no one manages to get pixel games to work as they should
     
  15. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    Fair point, hence I guess is the thread with generic discussion.
     
  16. CyRaid

    CyRaid

    Joined:
    Mar 31, 2015
    Posts:
    134
    The "classic" way to do it I suppose, would be to have a 2D array (like Rarac said), but find your tile map X position by doing a "SHIFT RIGHT" >> (way faster than division) which is why the tiles needed to be Power OF 2. So if your tiles were 16x16, you would shift by 4 leaving you with the tile #. I suppose you could have a bit which says horizontal/vertical, then some more bits deciding the "start pos" and the "slope" value (how many pixels before it shifts) and you'd be able to determine that based on your characer's position within the tile (with a bitwise AND). This all depends on a tilemap being a Power OF 2.

    In the end it'd be a shift, an array lookup and a 'jmp' if we're talking about branching based on the value, and then a bit more. These are just ideas, but if you're programming for a super low end device this would probably be the way to go without using expensive DIV's (especially floating point math, if the target device doesn't have SSE).