9
\$\begingroup\$

Sorry if the title isn't exactly what my question is, I don't really know how to describe it.

I have an image for my city floor and an image (same size) for all the walls or trees that the player is supposed to be hidden behind, if he walks past behind it. My result doesn't even look so bad:

The problem is that if the player walks infront of the wall, he vanishes, because the layerorder of the wall is above the order of the player:

enter image description here

Is there a rather simple way to fix this, or do I have to add all those objects manually and connect them to some scripts?

\$\endgroup\$
16
\$\begingroup\$

To achieve this effect:

Create two sorting layers: Ground and Objects.

Have your road, grass, and path sprites use the Ground layer.

Have your character, walls, and house sprites use the Objects layer.

Sprites on your Objects layer will want to have their Sprite Mode Pivot Point be either Bottom Left, Bottom, or Bottom Right. You can choose this by selecting a Sprite within your Project tab, and choose the pivot point in the Inspector tab to adjust the sprite's import settings.

Sprite Import Settings

For ground sprites, you won't have to worry about changing their order.

For objects, however, you can either change their Sprite Renderer's sorting order, or change their transform.position.z value. I'd recommend changing the transform, as the floats will probably be easier to look at and adjust as you move your character around, whereas changing the sorting order might not look as precise in certain situations, depending on the measurements and sizes of your objects in the scene.

In either case, some code will be needed.

public class SpritePositionSetter : MonoBehaviour {

    void Awake () {
        SetPosition();
    }

    void Update () {
        SetPosition();
    }

    void SetPosition () {
        // If you want to change the transform, use this
        Vector3 newPosition = transform.position;
        newPosition.z = transform.position.y;
        transform.position = newPosition;

        // Or if you want to change the SpriteRenderer's sorting order, use this
        GetComponent<SpriteRenderer>().sortingOrder = (int)transform.position.y;
    }

}

For either way of doing this, you're basically telling the sprite to have its Z index match its Y position.

If you attach this script to a static object (like a wall), you'll want to untick the component in the Inspector so that its Update method isn't called every frame; its Awake method will call SetPosition once and that's all you need.

But for your character, leave the component ticked so that Update will call SetPosition every frame, which will change the character's Z order as you move around. And as you move, as long as every sprite on the Objects layer is using a Bottom pivot point, changing the Z index as you move will ensure your character appears in front of or behind other objects appropriately.

Depending on your camera setup, you may need to multiply the new Z position by -1 if things seem backwards.

If you want to adjust the Z index while editing your Scene, check out ExecuteInEditMode.

\$\endgroup\$
  • \$\begingroup\$ I'm pretty sure that if the component is unticked Start() will nor run. Awake() runs on a inactive component, but start does not. \$\endgroup\$ – Uri Popov Apr 12 '16 at 7:35
  • \$\begingroup\$ Just checked; you're correct. I've updated the example to use Awake instead. Thanks \$\endgroup\$ – Chris McFarland Apr 12 '16 at 8:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.