Sprites/prefab with BoxCollider2D is not hit in correct order, what is wrong?

I am new to Unity and C# and I have 26 sprites (prefab) that I am placing on the screen, via code, on top of each other. I have tried without sorting order and with sorting order but get sort of the same result. They all have BoxCollider2D attached.

When i select the sprite on top it is selected some times and some times not.

  1. Clicked on top (queen) and it was selected and moved
  2. Clicked on the next sprite (king) that was on top and it got selected, and moved
  3. Clicked on the next sprite (knight) that was on top and the 9 is selected

The sprites 1 - 3 for the example above: 1595369--95925--$ee.png

I do not understand why i am not able to select the card on top, or the one i click on, and would like to get some help. I have been struggling with this problem for many hours. Initially i thought it was a ray cast problem.

The code attached to an empty game object:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class EGOScript : MonoBehaviour {

	public static List<string> cardDeckList = new List<string> {
		"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
		"14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26",};

	public GameObject theGameObject;
	float ff = 0f;
	public float addIT = 0.01f;
	int counter;




	
	// Use this for initialization
	void Start () {

		counter = 0;

		print (cardDeckList.Count);

		for (int z = 0; z < 26; z++) {

			theGameObject = Resources.Load(cardDeckList[z]) as GameObject;
			theGameObject.transform.position =  new Vector3(0f + ff, 0f + ff, 80f);
			theGameObject.renderer.sortingOrder = counter;
			Instantiate(theGameObject);

			ff = ff + addIT;

			counter++;

		}
	
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown(0)) {
			RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
			
			if(hit.collider != null) {
				print (hit.collider.tag);
			}
			
			
			
		}
	}


}

The code attached to the sprites:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class DragScript : MonoBehaviour {

	float x;
	float y;

	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		x = Input.mousePosition.x;
		y = Input.mousePosition.y;
	}

	void OnMouseDrag() {
		// Control the drag of the sprite
		transform.position = Camera.main.ScreenToWorldPoint (new Vector3 (x, y, 1.0f));
	}
}

I also lost control over the camera z-pos so i can’t really see the sprites unless i set the sprites z to 80?

Why is Z-pos on sprites change to -9 when clicked on?

I have also uploaded the test project here: http://www.filedropper.com/unityspritetest2

The “public float addIT” should be set to “0.01f”.

Appreciate all help i can get :face_with_spiral_eyes:

You can use the layers (Layers, not sorting layers)to ignore gameobjects.

Confflei, do you mean a layer per sprite? …could you please develop your answer a bit?

Hmmm has this anything to do with the fact that 2D “only” operates on the x y axis?

Have you tried using Physics2D.GetRayIntersection instead of Physics2D.Raycast?

GetRayIntersection detects intersections between a 3D ray and 2D colliders.

@Bivrost tested but the same result :frowning:

This is driving me crazy! …I even start thinking of going back to xcode as this should be a simple thing :frowning:

I have tried Bivrost suggestion as well as scanned the net for hours but it is still the same.

When i get this result: 1596246--96008--$Skärmavbild 2014-04-16 kl. 14.42.50.png the following applies:

  1. Click #1 top sprite (Queen)
  • Z = 70
  • Order in layer = 25, default sorting layer
  • Drag = OK
  1. Click #2 on King but J selected. K have:
  • Z = 80
  • Order in layer = 24, default sorting layer
  • Not selected
  1. When clicked on King J got selected and J have:
  • Z = 70
  • Order in layer = 23, default sorting layer
  • Selected when clicked on King

I do not understand how to use Z and sorting order and get the result i need and I am out of ideas how to solve this! I would REALLY REALLY appreciate if someone nice could show me, in code, how to place many sprites/prefabs on top of each other and then be able to a) click on the top one and drag it away and still select the sprite clicked, b) be able to click on any sprite that can be clicked individually and that is always selected.

I have linked to my project in my first post.

Thank you!

Hello,

Try this change to set the z values:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class EGOScript : MonoBehaviour {

	public static List<string> cardDeckList = new List<string> {
		"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
		"14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26",};

	public GameObject theGameObject;
	float ff = 0f;
	public float addIT = 0.2f;
	int counter;
	int zOffset;
	
	// Use this for initialization
	void Start () {

		counter = 0;
		zOffset = 26;

		print (cardDeckList.Count);

		for (int z = 0; z < 26; z++) {
	
			theGameObject = Resources.Load(cardDeckList[z]) as GameObject;
			theGameObject.transform.position =  new Vector3(0f + ff, 0f + ff, zOffset);
			theGameObject.renderer.sortingOrder = counter;
			Instantiate(theGameObject);

			ff = ff + addIT;

			counter++;
			zOffset--;

		}
	
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown(0)) {
			RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
			
			if(hit.collider != null) {
				print (hit.collider.tag);
			}
			
			
			
		}
	}


}

A quick test with Physics2D.GetRayIntersection worked for me. According to your code I also assigned the “Order in Layer” property and the sprite’s z-position. But maybe it’s not exactly what you wanted.

Nonetheless, here’s the test with a couple of overlapping sprites. Feel free to click on the infamous bird.

Web Player
Unity Project

BTW, see what MelvMay said about Physics2D.GetRayIntersection: Link

Thanks again Bivrost, checked your code. I tested the Physics2D.GetRayIntersection and it works but I saw no difference between that and Raycast.

I seems like it works now 98% with this code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class EGOScript : MonoBehaviour {

	public static List<string> cardDeckList = new List<string> {
		"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
		"14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26",};

	public GameObject theGameObject;
	float ff = 0f;
	public float addIT = 0.2f;
	int counter;
	public static int zOffset = 0;
	public static float zSelect = 26;
	public static int zSelectInt = 26;





	
	// Use this for initialization
	void Start () {

		counter = 0;
		zOffset = 26;

		print (cardDeckList.Count);

		for (int z = 0; z < 26; z++) {

			theGameObject = Resources.Load(cardDeckList[z]) as GameObject;
			theGameObject.transform.position =  new Vector3(0f + ff, 0f + ff, zOffset);
			theGameObject.renderer.sortingOrder = counter;
			Instantiate(theGameObject);

			ff = ff + addIT;

			counter++;
			zOffset--;
		}
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown(0)) {
			//RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

			Vector3 worldPoint = Camera.main.ScreenToWorldPoint( Input.mousePosition );
			worldPoint.z = Camera.main.transform.position.z;
			Ray ray = new Ray( worldPoint, new Vector3( 0, 0, 1 ) );
			RaycastHit2D hit = Physics2D.GetRayIntersection( ray );

			zSelect++;
			zSelectInt++;
			
			if(hit.collider != null) {
				//print (hit.collider.tag);
				//zSelect = hit.collider.transform.position.z;

				Vector3 z3 = hit.collider.transform.position;

				z3.z = zSelect;

				hit.collider.transform.position = z3;
				hit.collider.renderer.sortingOrder = zSelectInt;

				print (hit.collider.transform.position + " + " + zSelectInt);
			}
		}
	}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class DragScript : MonoBehaviour {

	float x;
	float y;
	float z;


	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		x = Input.mousePosition.x;
		y = Input.mousePosition.y;
	}

	void OnMouseDrag() {

		// Control the drag of the sprite
		transform.position = Camera.main.ScreenToWorldPoint (new Vector3 (x, y, EGOScript.zSelect));
	}
}

Again thanks.