Dynamic draw order or '2D Z-buffer'?

Hi,
In a 2D isometric game, how do you handle the draw order of the character and objects like walls and crates?
Wall sections/ a building or things like that, are just sprites and have no real depth, and our character as well, but it needs to draw on top of them when standing in front, and draw behind when standing behind… How is this handled?

Thanks.

You can still use the Z position value for this, no?

Use the Order In Layer variable

OK, I can change the Order In Layer technically, but how do you detect when the player, or anything else, is behind or in front of the object?
Maybe you can model a proxy mesh to fit the object, or define two regions on the ground for collision and for culling?
Think about games like commandos, everything is hand-drawn, but you ca still go behind trees, houses and such.

Well why do you want to “detect” when one object is behind another object?
Note that alternatively you can establish several “Sorting Layers”. This is different than Order In Layer.

Ok, to be honest Im not sure I understand you. Maybe I’m not explaining myself very good.
The best way would be with an image:
1469668--80710--$problem.jpg

If the house is our sprite, and the character walks around it, the draw order should change when the character goes under the roof. This is not so simple, unless I miss something. I guess a combination of separating the house to multiple sprites, and using the Y position of the character as a fake Z can do the trick, but its not very elegant

Looks like you should be using the 3D engine, not the 2D engine. You can still lock the camera to a side view perspective, so that it appears 2D, but functionally it will be 3D, and therefore more naturally and easily handle objects walking around other objects.

OK, do you think thats how it works in games like Commandos and Desperados? Every building is represented by a proxy mesh with textures? Modelling the entire assets is very time consuming/requires too many polygons to reach painted quality no?
Sorry if this is just basic stuff that I don’t understand, I’m new to this…
Thanks a lot.

Well for what it’s worth, Rovio used the Unity 3D engine with a camera locked to the side view when they created the game Bad Piggies…
http://unity3d.com/gallery/made-with-unity/profiles/rovio-badpiggies

The way I do this is to put a trigger zone behind the object, so when the player (or some other character) walks into that area, you can either move the object forward or move the player back. Previously I was doing this by setting the Z-value but now you could probably just edit the order in layer.

It is time-consuming, especially tweaking the trigger to be the exact right shape that you don’t notice the change when walking on corners etc. But with some art styles it is basically impossible to make a 3D representation of an object so I’m not sure what other choice there is than to leave it 2D and do this.

I find setting Z values works well. Sometimes you need to split a sprite into two or more pieces with different depth values, but it’s not as much trouble as creating an entirely 3D model - they’re still just layers. Using triggers is an interesting approach but also feels kind of complicated, and awkward to get working with multiple characters wandering around.

gfoot~ Could you tell me How to set the Z value ?
It seems the z value in the inspector is not working.

Hi, I think we are facing exactly the same problem.
With the search I have done, I think you should use the 3D engine with a fixed camera like explained above.
You cannot handle changing sorting layers on real-time. If you had only one moving character, it would be possible but for 50 units… and one time you will be in the case where a character is in front of the building and one on the back at the same time.

You can then apply your 2D “texture” on a 3D block and move it in a 3D coordinates system which will hande the Z-Depth.

If the result is successful please write it here :slight_smile: With a screenshot… I love real example :wink:

ijj, it just works flawlessly for me. I do use sorting layers for most things, but have used Z depth for other things without problems.

I just tested it again to make sure, and it works fine. This test was in a project which was started from the beginning in 2D mode, so there are no 3D remnants. The sprites are just normal sprites - PNG files in the assets folder, dragged into the scene. The sprites with lower transform.position.z values render in front of sprites with higher Z values, in both the scene view and the game view, including when the position is changed from script at runtime.

All these sprites must be in the same sorting layer and with the same ‘order in layer’ value. Put another way, the sorting layer is the highest priority control over these overlaps; then order in layer comes next; then actual Z depth from the camera. So you can freely mix the techniques, sticking to sorting layers for most things (e.g. making the ground render behind the house and characters, and making UI elements render on top of everything else), but using Z depth as a last resort for more dynamic, continuous order changes.

Remember again that for some sprites you might want some parts to have different depth to other parts. In an isometric game, with the grid X and Y axes inclined at equal angles to the screen horizontal, this would happen for objects with a rectangular profile on the grid - the left extent of the object in screen-space would be at a different distance from the camera, in a true 3D world, than the right extent. In that case you may want to cut the sprite down the middle and render it as two pieces with different Z values. Another approach is to rotate the sprite about the camera’s up axis and scale it up a bit, to have a linear depth gradient across the sprite. This should work fine for almost any object in an isometric game.

Hey, I just posted this in another thread as well but since it’s the same question I’ll answer here as well:

The render order determined this way : Sorting Layer > Order in Layer > Z transform . That’s why I decided to do things this way:

-all foreground elements are on the same Sorting Layer
-each element has a script attached, that changes the Order in Layer according to the Y position of it’s feet/base
-if I have a gameobject that consists of multiple sprite child objects (character limbs or so), I assign the same Order in Layer for all components and then adjust the sorting of the children via the z transform

This also leaves you with the ability to use the Z transform in animations (limbs moving behind other limbs and so on).

Do you think, without cutting each sprite in two parts, that it can solve the following :

1475690--81412--$Unity_human_Back.jpg
1474846--81324--$Unity_human_In_Front.jpg

My little boy is moving around the castle, and everything is fine all the time…
If you try to change the Sorting layers by script depending of the position of the guy, it won’t work if you have one guy back, and one front at the same time…

Is 2D still a real solution ?

As I said, I don’t change the sorting layers, but the Order in Layer.

Let’s say the center of the castle has a Y coordinate of 10. That sets the Order in Layer to -10
If the player moves lower than the center of the castle, his Y coordinate would be something like 8, making his order in Layer -8, thus rendering him in front of the castle.
If the player moves above the center of the castle, his Y coordinate will be something like 12, making the Order in Layer -12 and rendering him behind the caslte.
This works with as many characters as you want, because each character updates it’s own Order in Layer.

In this case you wouldn’t have to split the sprite, just take the center diagonal as the castles “base”, and the character’s feet as the character’s "base. If you have more complex structures, you might have to split them up at some point. (the drawbridge here might cause issues for example)

3 Likes
void LateUpdate () {

				spriteRenderer.sortingOrder = (int)Camera.main.WorldToScreenPoint (spriteRenderer.bounds.min).y * -1;
		}

This is basically what I do. This script assumes the base of the character is at the bottom of the sprite though, which isn’t the case in isometric 2D.
With base I mean the horizontal line at which you decide what is in front and what is behind. In isometric it should usually be the horizontal diagonal of the sprite, so just change the script according to that.

7 Likes

TaewYn, your technique is interesting - I hadn’t had to deal with the characters themselves requiring multiple overlapping layers. Certainly a problem with doing it with transform.position.z is that you’re sensitive to Z buffer resolution - not a major problem but you do need to be careful to use large enough offsets between “layers”.

technos, as TaewYn said I think you should be able to use these techniques, but as I said before the ground is going to cause you problems unless you separate it into a separate sprite on a more distant layer. To see why, look at the case where your character is behind the castle, and imagine moving him towards the castle so that his sprite needs to be rendered on top of the surrounding ground, but behind the castle itself. It means that you need the ground and castle to be rendered separately, unless this is prevented by your collision detection - but your other image shows the character with his foot on the castle’s tile, so I guessed your collision detection isn’t so strict.

Indeed, what TaewYn described is the usual approach to this. Whether using Unity or not. If you want to use ground textures (apart from the base ground), treat them separately from objects that will cull the characters. Additionally, if you want to have elements that characters walk through (arches/doorways/etc), just cut them logically along the Y and place one in front of the other.