Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

Correct way to deal with sorting layers in a top down 2d game?

Discussion in '2D' started by iluvpancakes, Sep 3, 2020.

  1. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Hi, So I am playing around in Unity 2D, trying to figure out how to build a simple top-down 2d game. My current issue is how to have the player render correctly depending on where they are in relation to an environment object, such as a plant or tree.

    When I use tile maps to include these assets I find it extremely hard to get a fluid layer sorting happening, especially if some objects are built up of several tiles, or exists at the intersection such as this:
    halfvisible.PNG
    So I am immediately drawn to the idea of keeping all sprites that are not strictly background/ground tiles as separate gameObjects with their own sprite-renderer component instead since it gives me much more freedom in terms of placing such assets without messing up tilemaps by trying to edit the sprite sort point etc.

    I am however unsure if this will draw any significant overhead in the long run or not? Is this the most efficient way of solving the issue I am having at the moment? Is it unusual for a (modern) 2d top down game to have trees and other obstacles as separate entities?

    I guess in short I would love to know what is considered industry standard when dealing with these issues in a top down game? Using Tilemaps for all buildings and trees, pretty much anything that is not a unique object and then be a Unity software ninja and solve it somehow or to place all objects you want to be able to walk behind or in front as separate gameObjects? Or maybe a 3rd option which i am totally unaware of?

    I am using Unity 2019.4.9f1 and Transparency sort mode is set on Y:1

    Any ideas and tips are greatly appreciated, thank you.
     
  2. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,533
    For both SpriteRenderers and Tilemaps, you should be able to adjust the sprite's Pivot Point within the Sprite Editor to the correct spot so it sorts properly. It also depends on your character's body/feet.

    Tilemaps have less overhead that SpriteRenderers, so they're preferable all else equal, but you shouldn't feel strictly bound to them. Also you are hopefully using Individual mode for your TilemapRenderer or else it won't sort well.

    Other components to be aware of are the Sorting Group. If you have a collection of sprites (e.g. the character) that you want to ensure sort by the parent y-position, you can assign them a Sorting Group to the topmost one. The child renderers then obey the SpriteRenderer's Order setting, sorting first by their parent's position then by their order among themselves. If the parent is position (relative to the children) is near where the feet are it should work out for correct sorting.

    https://docs.unity3d.com/2017.1/Documentation/Manual/SortingGroup.html

    If it's not working out for you after some more effort, post more screen shots so we can troubleshoot.
     
    Tirt and ChillyRolande like this.
  3. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    When I adjust the individual pivot point of a sprite, as the one in the example the tile of course changes where it is rendered and it does no longer line up with the rest of the three tiles (in the brush example above). This was the first thing I tried since I already have the players pivot point somewhat below the characters rendered feet. But the same applies for the player sprite. When I adjusted the Y value to -0.1 to get the sorting to happen at the point I wanted to the character also rendered 0.1 units higher on the screen since, AFAIK, the sprite renderer consider the pivot point to be the reference point from where it renders the sprite. So unless there is a smart way to negate this behavior I can not apply it to things that are built up from several tiles, and even if I did they would all have a different pivot point anyways.

    Yes, I am.

    I thought you needed a spriterenderer component in order to create sorting groups? Since my tilemap is using tilemap renderer I did not think this was an option? I am guessing that if I they were a gameObject with spriterenderer components I would then be able to set a pivot point which all the children obeyed uniformly as a group? If so, yes that would help if I could apply this to a tilemap renderer without having to make a separate Tilemap for each brush/tree/house etc.

    Thank you so much for taking the time to reply, It is the first time I ever had a reply on something Unity related I posted anywhere (stackoverflow, unity 2d subreddit, here, unity Answers), compared to when I post c# related questions on any related community page where people are eager to jump in and help, not sure why this is? Are there better places to post questions related to unity 2d that I am unaware of? Again, thanks a lot for the effort and let me know if I can provide you with anything else, if screenshots would help just tell me what you want me to upload and I'll do it.
     
  4. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,533
    Your tilemap settings may be wrong etc. It's hard to say without pictures of where your tiles are, where the grid lines for the tiles are, your transform hierarchy etc.

    Let me describe a general test case that you can set up to make sure you get the character and a tree sorting. We're going with tree b/c it's a tall sprite. Make a tile for it and place it on the tilemap. Adjust its pivot point so that the tree's base is at the center of the tile it is placed in (so its branches are above that tile). Place several. Then prepare the character. Give its parent gameobject a Sorting Group. Give the child SpriteRenderers (assuming your character is multiple sprites) Order setting so they render in the right order. They will behave as if the z-position is where the parent sprite is (so, the feet). Adjust the position of them all relative to the parent.

    Here's a simple example where I have a sorting group on parent SpriteRenderer and demonstrating correct sorting against a wall. Child to the "body" (a single sprite for simplicity) are the head and hair, separate GameObjects w/ SpriteRenderers. The parent could be an empty GO so long as it has the Sorting Group component iirc. Also note that the SpriteRenderer is set to Pivot for each.
    sort2.gif

    Yes, that's correct. GameObject + SpriteRenderer, not Tilemap.

    -----

    It might be helpful to make a short gif showing what you're seeing and how your setup looks. There's a free open source program called ScreenToGif for this purpose. That way it would be possible to see how things sorting against one another and you drag your character around. I don't know how your character is composed etc.

    -----

    For general 2D learning you should check out Unity's YouTube (and there are plenty of other YouTube creators who make content on 2D stuff), as well as Unity's Learn pages. Likewise, Unity has example projects. That might be the most helpful for you.

    https://learn.unity.com/
    https://github.com/Unity-Technologies/2d-renderer-samples
    https://github.com/Unity-Technologies/2d-gamedemo-robodash
    https://github.com/Unity-Technologies/2d-techdemos
    https://github.com/Unity-Technologies/2d-extras
    https://github.com/Unity-Technologies/2d-pixel-perfect
    https://github.com/Unity-Technologies/PhysicsExamples2D
    https://github.com/Unity-Technologies/2d-animation-v2-samples
    https://blogs.unity3d.com/2019/12/18/download-our-new-2d-sample-project-lost-crypt/
     
  5. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Just to clarify before I make an example to show you. Are those pillars-walls made up of several smaller tiles which include 4 intersecting tiles? Because I can achieve the same effect using brushes that fit within one tile without a problem, the issue I was having was specifically with intersecting tiles. Anyways, I will build a scene which clearly demonstrates what I am having issues with and I will also follow the steps you wanted me to reproduce ASAP. Probably will take me an hour or two until I can make time for it. Thanks again!
     
  6. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Okay, here goes. First my settings:
    Camera settings:
    camera-settings.PNG
    Foreground tile layer settings:
    foreground_tile_layer.PNG
    Sprite carrying child of player gameObject (I just quickly sat up a new project for this so just one sprite):
    spriteCarryingChild.PNG
    Pivot setting in sprite editor (I adjust this later to get it better, important thing to note is that I know the implications of it):
    pivot_location_player.PNG
    When checking sorting vs anything made up of ONE tile (never had issues with this btw):
    crop-sorting.gif
    Continue in next post, 5 document limit for me to upload.
     
  7. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Continuation from previous post:

    Another example using a tree consisting of ONE tile (Again, this has always worked):
    tree-sorting-One-Tile.gif

    What I am having issues with are multi-tile objects, which occurs if I want to be able to place a tree/brush/whatever that is NOT centered on a tile:
    tree-sorting.gif

    This tree is made up of 6 tiles (could be two in this instance but pretend I wanted to place this tree at a tile intersection (the center point of 4 tiles), then I don't know what to do since it breaks like this.

    If I try (I explained this in my previous post but might have been hard to get what I meant without images) to adjust the pivot point of each separate tile like this:
    tree_pivot_after_edit.PNG

    it obv breaks:
    after_pivot_adjustment.PNG

    Let me know if I explained my dilemma clearer now. Thanks for your patience!
     
  8. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,533
    Ah, so that's what I was wondering: whether you're splitting the tiles up. I thought the character might be separate pieces, not the tiles. In my example gif, it's 1 sprite for tile.

    The easiest solution is to not split the tiles up. There is very little advantage to spliting: it's more sprites to be rendered.

    However, in the case that you really want to - let's say you want to share trunks between several tree varieties - then you could solve this a couple ways:
    1. the pivot points in the same spot for both canopy and trunk - it might require some effort to get it exactly right. You've already found this to be difficult. So simplify: only have a canopy and only have a trunk. So long as they're very close people are unlikely to find the 1/100th discrepancy from imperfectly placed pivot points. If needed, colliders can make up for the difference.
    2. top and bottom layers: draw so that the trunk is always going to be rendered under the character, and the canopy is always going to rendered above the character. Place trunk and canopy tiles on different tilemaps with Order settings so that trunks always below and canopy all the way above. Again, if needed, colliders can make it harder to walk in a bad spot. Edit: this also has the advantage that you could probably get away with chunked tilemaps (which are more efficient) for both top and bottom layers.
    Don't forget, players are going to be interested in interacting with your world, not discovering the very slight y-position that makes sprites look bad. Unless your player has a specific reason to stop moving under a tree, if the issue ever shows up it'll exist for 1 frame. Again, it's easiest to not split sprites up at all.
     
    Last edited: Sep 4, 2020
  9. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Thanks for the clarification, everything was, mostly, as I suspected. I had hoped that there was some Unity2D ninja skills that I had not discovered that could tackle this problem more elegantly, but your tips and suggestions are very much appreciated nonetheless!

    So let's say I wanted to have a forest of trees where they are, at times, all packed together much more tightly than what tile placing would allow and you still want to use tile-maps due to efficiency, would you just add a bunch of trees with different pivot offsets in different layers to get them to "overlap" etc? At this point we would worry less about the sorting order compared to the player, lets pretend that this use case is a forest that serves like a backdrop and the player can not enter the forest at all. Or would it be easier to do it another way?

    If you don't have time to answer further questions I understand and take no offense, just thought I'd ask since this would be my natural follow up question at this point.

    So in either case, thanks for the help and effort!
     
  10. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,533
    You might need to sketch what you mean by overlap. There are so many ways to do things, both in implementation and art, that it's hard to guess what you mean exactly. If really dense, you only need the canopies of the trees because no trunks will be visible. It probably could go on a single tilemap with wider-than-cell (overlapping) canopy sprites.
     
  11. raarc

    raarc

    Joined:
    Jun 15, 2020
    Posts:
    535
    its okay to use game objects for this as long as you unload the map when the objects are offcamera, think of it like minecraft when you approach an area it loads, when you leave it it unloads, in a topdown perspective you can do this seamlessly, even if you do this using tilemaps you will need to do it unless you make very small maps per area( like stardew valley)
     
  12. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Ah right, I guess I just make a save state of the area (if I want any persistent changes made to it) and reload it. I was thinking about this because a player might want to chop down a tree or make other changes to these objects which kind of forces me to have them as gameObjects right? Especially if you want something to change over time independently of other sprites in a tilemap?
    Thanks for the input raarc!
     
  13. iluvpancakes

    iluvpancakes

    Joined:
    Jul 19, 2020
    Posts:
    18
    Yeah i get what you mean, I will update the thread when i get there and if you're still around I would love feedback at that point, all the best until then!
     
  14. raarc

    raarc

    Joined:
    Jun 15, 2020
    Posts:
    535
    yes you cant make tiles shake or tilt, its better to use game objects for trees, bushes and crops, it is worse for performance but as long as you only load what needs to be onscreen it wont be a problem
     
  15. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,533
    You can make tiles shake and tilt, it's just not friendly :p Manipulate the Matrix4x4 directly via tilemap.SetTransformMatrix(cell, matrix).
     
  16. PuppyPolice

    PuppyPolice

    Joined:
    Oct 27, 2017
    Posts:
    116
    Yeah you can make tiles shake, tilt, move around basically just like anything you can do with the transform you can do with tiles but if you want to do some complex animations, like falling trees, I would suggest using gameobjects because doing animations for a gameoobject is much easier since you can use Unitys animator system + monobehaviour, if you wanted to do complex animations with only tiles you gonna have to write the calculations yourself.

    If you are worried of performance you can always combine tiles with gameobjects, where you use tiles and only when you need complex behaviour, for example a player tries to chop down a tree, you can replace the tile with a gameobject instead that has all the functions and behaviours you need and once the player leaves the area you can just pop the gameobject into a object pool.
     
  17. jjohn8521

    jjohn8521

    Joined:
    Sep 25, 2017
    Posts:
    7
    just wondered if you finished your game, OP :)