How to apply OnMouseDown on sprites according to z position...

25558-screenshot_2014-04-22-13-10-52-1.png -4.1 then -4.2 so they are positioned on one another… all have 2d box collider and script applied to destroy petal on onmousedown… the problim is , when i click on the front most petal positioned suppose on -5 it destroys any of the petal positioned underneath it , like in between -4.9 to -4.1 … what i want is . it should detect the front most collider sprite first rather then the collider applied on the underneath petals… i also have tried help form here
but its not working :frowning:

function OnMouseDown()
{
//	print("ok");
	Destroy(gameObject);
}

Hi Omer, you need to get rid of the OnMouseDown function altogether to use a raycasting method.

Step 1: Attach the frontmostspriteclicker script to your main camera.

Step 2: Anything with a collider that you want to be able to click on must have a script attached with a function in it called OnLeftClick. If it is one of the petals you might want something like

function OnLeftClick(raycastHit : RaycastHit2D)
{
//  print("ok");
    Destroy(gameObject);
}

Step 3: Re-writing the script to use z depth won’t be too complex (afraid I don’t have time to do it right now) but it would be something like, where you see this code:

// Loop through the array of raycast hits...
                for (var i = 0; i < hits.length; i++)
                {
                        // Get the SpriteRenderer from each game object under the click.
                        spriteRenderer = hits*.collider.gameObject.GetComponent(SpriteRenderer);*

// Access the sortingLayerID through the SpriteRenderer and store it in the sortingLayerIDArray.
sortingLayerIDArray = spriteRenderer.sortingLayerID;

// Access the sortingOrder through the SpriteRenderer and store it in the sortingOrderArray.
sortingOrderArray = spriteRenderer.sortingOrder;
}
Don’t bother accessing the sprite renderer at all and just store the z depth in an array:
hitDepth = hits*.collider.transform.position;*
And then where you see this code:
// Loop through the array of sprite sorting layer IDs…
for (var j = 0; j < sortingLayerIDArray.length; j++)
{
// If the sortingLayerID is higher that the topSortingLayer…
if (sortingLayerIDArray[j] >= topSortingLayer)
{
topSortingLayer = sortingLayerIDArray[j];
indexOfTopSortingLayer = j;
}
}
Put something like:
if (hitDepth[j] >= topSortingLayer)
{
topSortingLayer = hitDepth[j];
hitDepthOfTopSortingLayer = j;
}
Hope that helps, I wish I had more time to rewrite the code properly. Let me know how you get on, I’d love to include a link to a Z depth sorting sprite clicker on the site :slight_smile:

#pragma strict

private var leftClickedObject : GameObject;
private var rightClickedObject : GameObject;
private var frontmostRaycastHit : RaycastHit2D;
//private var hitDepth[]:Transform;
 
// It's necessary to access the SpriteRenderer of a game object to be able to access its sorting layer ID
// and sorting order ("Order in Layer" in the inspector)
private var spriteRenderer : SpriteRenderer;
 
function Update ()
{
        // If the left mouse button is clicked anywhere...
        if (Input.GetMouseButtonDown(0))
        {
                // frontmostRaycastHit stores information about the RaycastHit2D that is returned by GetFrontmostRaycastHit()
                frontmostRaycastHit = GetFrontmostRaycastHit();
 
                // If frontmostRaycastHit is true, i,e the user hasn't clicked on nothing, i.e GetFrontmostRaycastHit() didn't return nothing...
                if (frontmostRaycastHit)
                {
                        // Assigns the game object that the collider that has been clicked on to leftClickedObject.
                        leftClickedObject = frontmostRaycastHit.collider.gameObject;
                       
                        // Sends the frontmostRaycast to a function called OnLeftClick in a script attached to whatever the leftClickedObject is.
                        leftClickedObject.SendMessage("OnLeftClick", frontmostRaycastHit, SendMessageOptions.DontRequireReceiver);
                }
        }
        // If the right mouse button is clicked anywhere...
        else if (Input.GetMouseButtonDown(1))
        {
                // frontmostRaycastHit stores information about the RaycastHit2D that is returned by GetFrontmostRaycastHit()
                frontmostRaycastHit = GetFrontmostRaycastHit();
 
                // If frontmostRaycastHit is true, i,e the user hasn't clicked on nothing, i.e GetFrontmostRaycastHit() didn't return nothing...
                if (frontmostRaycastHit)
                {
                        // Assigns the game object that the collider that has been clicked on to rightClickedObject.
                        rightClickedObject = frontmostRaycastHit.collider.gameObject;
                       
                        // Sends the frontmostRaycast to a function called OnLeftClick in a script attached to whatever the rightClickedObject is.
                        rightClickedObject.SendMessage("OnRightClick", frontmostRaycastHit, SendMessageOptions.DontRequireReceiver);
                }
        }
}
 
function GetFrontmostRaycastHit(): RaycastHit2D
{
        // Store the point where the user has clicked as a Vector3.
        var clickPosition : Vector3 = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        // Retrieve all raycast hits from the click position (to the same click position - more a dot than a ray) and store them in an array called "hits".
        var hits : RaycastHit2D[] = Physics2D.LinecastAll (clickPosition, clickPosition);
 
        // If the raycast hits something...
        if (hits.length != 0)
        {
                // A variable that will store the frontmost sorting layer that contains an object that has been clicked on as an int.
                var topSortingLayer : int = 0;
                // A variable that will store the index of the top sorting layer as an int.
                var indexOfTopSortingLayer : int;
                var hitDepthOfTopSortingLayer: int;
                // An array that stores the IDs of all the sorting layers that contain a sprite in the path of the linecast.
                var sortingLayerIDArray : int[] = new int[hits.length];
                // An array that stores the sorting orders of each sprite that has been hit by the linecast
                var sortingOrderArray : int[] = new int[hits.length];
                // An array that stores the sorting order number of the frontmost sprite that has been clicked.
                var topSortingOrder : int = 0;
                // A variable that will store the index in the sortingOrderArray where topSortingOrder is. This index used with the hits array will give us our frontmost clicked sprite.
                var indexOfTopSortingOrder : int;
 
                // Loop through the array of raycast hits...
                for (var i = 0; i < hits.length; i++)
                {
//                        // Get the SpriteRenderer from each game object under the click.
//                        spriteRenderer = hits*.collider.gameObject.GetComponent(SpriteRenderer);*

//
// // Access the sortingLayerID through the SpriteRenderer and store it in the sortingLayerIDArray.
// sortingLayerIDArray = spriteRenderer.sortingLayerID;
//
// // Access the sortingOrder through the SpriteRenderer and store it in the sortingOrderArray.
// sortingOrderArray = spriteRenderer.sortingOrder;
_ var hitDepth = hits*.collider.transform.position;
}*_

// Loop through the array of sprite sorting layer IDs…
for (var j = 0; j < sortingLayerIDArray.length; j++)
{
// If the sortingLayerID is higher that the topSortingLayer…
// if (sortingLayerIDArray[j] >= topSortingLayer)
// {
// topSortingLayer = sortingLayerIDArray[j];
// indexOfTopSortingLayer = j;
// }
* if (hitDepth[j] >= topSortingLayer)*
* {*
* topSortingLayer = hitDepth[j];*
* hitDepthOfTopSortingLayer = j;*
* }*

}

// Loop through the array of sprite sorting orders…
for (var k = 0; k < sortingOrderArray.length; k++)
{
// If the sorting order of the sprite is higher than topSortingOrder AND the sprite is on the top sorting layer…
// if (sortingOrderArray[k] >= topSortingOrder && sortingLayerIDArray[k] == topSortingLayer)
// {
// topSortingOrder = sortingOrderArray[k];
// indexOfTopSortingOrder = k;
// }
// else
// {
// // Do nothing and continue loop.
// }
* if (hitDepth[k] >= topSortingLayer)*
* {*
* topSortingLayer = hitDepth[k];*
* hitDepthOfTopSortingLayer = k;*
* }*

// How many sprites with colliders attached are underneath the click?
Debug.Log("How many sprites have been clicked on: " + hits.length);

// Which is the sorting layer of the frontmost clicked sprite?
Debug.Log("Frontmost sorting layer ID: "+ topSortingLayer);

// Which is the order in that sorting layer of the frontmost clicked sprite?
Debug.Log("Frontmost order in layer: "+ topSortingOrder);

// The indexOfTopSortingOrder will also be the index of the frontmost raycast hit in the array “hits”.
return hits[indexOfTopSortingOrder];
}
}
else // If the hits array has a length of 0 then nothing has been clicked…
{
Debug.Log(“Nothing clicked.”);
return;
}
}

OK … for everyone who is suffering from this problem … Solution is …

  1. Apply 2d collider on the sprite
  2. Keeps the Sprites According to the Z position. For example, if your camera is at -10 z position , your background could be at -5 , characters could be at -6 and forground at -7.
  3. If 2d collider doesn’t fit to the sprite position , for example if you have star or sprite like zigzag/not equal than use 2d Polygon Collider(atleast it helped me in this situation).
  4. I dont know layered effect or not but try to keep the layers dafault.

Have Fun … :slight_smile: Finally i am out of The Hell of 2D Collider … :wink:
and i used
function OnMOuseDown(){
//////do what ever you want to do here
}