Is Selective Y-Sort Possible?

Godot Version



This may seem like a dumb question, but is there a way to selectively Y-sort?

I am making a top-down RPG. I have a bush in my world. I want the player and all ground-based enemies to collide with and Y-sort around this bush, but I want floating enemies to just fly over it, not colliding with it and always appearing on top of it rather than Y-sorting around it. Can you picture this? Makes sense, yeah?

Unfortunately, since the floating enemies don’t collide with the bush, they instead appear to just clip thru it thanks to Y-sort, which is not what I want. Y-sort needs to be turned on for them as I do want them to Y-sort with other things like the player, trees, etc.

I cannot think of a way to make this work, unless there is a selective Y-sort setting that I’m unaware of.

I don’t think using Z-index is the solution here, as I still want the floating enemies, grounded enemies, player, and other world elements to Y-sort properly, which means they all have to be on the same Z-index. If I change the floating enemy Y-sort to +1, it will always draw on top of the player, taller world elements, etc. and that would not be good. I also don’t want to raise the sprite up off of its origin, as I like where it is.

I hope what I’m asking for makes sense. I can include some gameplay or code if needed, but I figured it wasn’t really necessary. Thoughts?

Do you mean you want to implement some kind of height levels? As far as I know, a common way to achieve that is making game 3D and then using a fixed camera angle to achieve fake 2D top down view. That probably is not an option unless you just started your project and even then I would assume fake 2D will introduce an entirely new set of problems.

Another way I can think of is separating sprites/tiles into parts based on their height and changing their z-index. I’m not sure how well that would work though.

To me this seems like the exact case Z-indexes are intended for :thinking: But could be I’m missing something.

The flying entities should be in front of the ground units and so on. If there’s an entity e.g. high pillar that they should be able to be behind of then I would split the pillar sprite in two and have the part that’s “in the sky” share the “air” Z-index.

If you could post an example of what’s wrong or what should happen maybe I would understand better :slight_smile:

Hmm yeah I am just making it in 2D and don’t want to switch haha, but thanks. The issue with Z-indexing it is that the bushes, trees, and ground-based kinetic bodies like ground enemies, the player, and NPCs need to be all on the same Z-index so that they Y-sort correctly. If I change the floating enemies to be a higher Z-index, they will always draw on top of all grounded assets which is not the desired result. The floating enemies still need to Y-sort with all grounded assets else it won’t look right.

Unfortunately, the floating enemies should not be in front of ground units (besides bushes), especially static units like tall trees, as that would not look right. Even if I split the sprite that won’t fix everything, though I wish that were the case!

In this video, you’ll see the bat clips thru the bush, then later at the end goes behind one. It’s very inconsistent. I think maybe it has something to do with the fact that I use spawners to spawn the enemies, but I spawn them as children of a Y-sort node, same as everything else, and the enemies themselves have Y-sort on. It should work correctly, but idk. Regardless…you can hopefully see how it would make sense for me to want the bat to Y-sort with the player and almost everything else on the ground, but always be in front of low-ground units like bushes.

Ah now I get it. You should offset the bat’s position so that the point used for ysorting isn’t at the sprite’s center - it should be at the center of the shadow. This is because that’s the x, y position the bat is actually at. It’s flying (up in the third dimension) but this shouldn’t affect its y position.

I don’t remember how exactly Ysorting works nowadays so this may be wrong but I think Sprite2D has an offset variable you can change. Use this to move the bat up so that the actual center of the sprite is where the shadow is but the bat appears to not have moved.

Alternatively you could add empty space below the spritesheet but I think the offset solution is more elegant.

1 Like

Yep, that was it! I did have my sprite offset from the bat scene center and thought that was all I needed to do, but I was using the Transform property to move it up rather than the Offset property. Simple mistake. I knew it had to be something like that, thanks a lot!

1 Like