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:
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.
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 sort by parent’s y-position, then 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 and then by their order among themselves. Often the best place for the parent Sorting Group is where the feet or base of the object is.
If it’s not working out for you after some more effort, post more screen shots so we can troubleshoot.
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.
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.
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.
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!
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):
When checking sorting vs anything made up of ONE tile (never had issues with this btw):
Continue in next post, 5 document limit for me to upload.
Another example using a tree consisting of ONE tile (Again, this has always worked):
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:
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:
it obv breaks:
Let me know if I explained my dilemma clearer now. Thanks for your patience!
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:
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.
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.
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!
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.
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)
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!
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!
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
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.