Hello again.
I have a very simple question. When many sprites overlap each other and I wanna for example drag one, how can I find, which one is on the top? Do I have to compare Sorting layers and order in layers? Or is it possible to stop the ray after “first” hit?
Thanks for any tips.
Have a nice day!
Could we see some code? How are you doing the raycasting?
You should try Linecast if you aren’t already, it will return the first one hit and allows you to ignore layers:
Well, I this is part of my code:
void OnMouseOver(){
if(Input.GetButtonDown("Bend") !bend ) {
create = true;
clickedPos = mousePos;
bend = true;
}
}
I need to launch that code only when there’s no sprite overlaping this object on MousePosition. They are both in the same sorting Layer, but have different order in Layer…
For example, I have three same objects with this script overlaping each other and I want to achieve Drag&Drop effect. I want to drag only the object on the top.
Is there any elegant way to solve this?
Thank you very much for response, Invertex!
Welp, took me a bit to figure out a method, but I think I solved it for ya! Most of it is explained in the commenting on the code.
Though I will mention that the “bendLayers” is for the Inspector Layers, not your Sorting Layers, it’s so you can restrict the raycast to only take into account objects that are in certain layers. So put objects you want to be affected by this, in their own layers or single layer and set the layer names in here. (The script itself still compares your Sorting Layers though, don’t worry about that! haha)
private bool create = false;
private bool bend = false;
private Vector2 clickedPos;
private LayerMask bendLayers;
void Start ()
{
bendLayers = (1 << LayerMask.NameToLayer("Gems")) //Set the layers you want to be clickable here, duplicate the lines for however many you need
|(1 << LayerMask.NameToLayer("Ground"))
|(1 << LayerMask.NameToLayer("Cats"));
}
void Update ()
{
if(Input.GetButtonDown ("Bend") !bend)
{
clickedPos = Camera.main.ScreenToWorldPoint (Input.mousePosition); //Get current worldspace position of mouse cursor
RaycastHit2D[] hits = Physics2D.LinecastAll(clickedPos,clickedPos,bendLayers); //Cast ray at the world space the mouse is at
if(hits.Length > 0) //Only function if we actually hit something
{
int topHit = 0; //Set our top hit to a default of the first index in our "hits" array, in case there are no others
int preValue = hits[0].transform.GetComponent<SpriteRenderer>().sortingLayerID; //Set our first compare value to the Sorting Layer ID of the first object in the array, so it doesn't get skipped
for (int arrayID = 1; arrayID < hits.Length; arrayID++) //Loop for every extra item the raycast hit
{
int tempValue = hits[arrayID].transform.GetComponent<SpriteRenderer>().sortingLayerID; //Store Sorting Layer ID value from the current item in the array being accessed
if (tempValue > preValue) //If the Sorting Layer ID value of the current check is higher than the previous, update values
{
preValue = tempValue; //Set the previous highest value to the current one just checked, for comparison later in loop
topHit = arrayID; //Set our topHit with the index value of the current Array item that has the highest Sorting Layer ID
}
}
create = true;
bend = true;
//You can directly get a component of the hit object here to modify that clicked object
//hits[topHit].transform.GetComponent<Whatever>();
//hits[topHit].transform.position = whateverPosition
//etc....
}
}
}
This could be modified to also take into account the “Order in Layer” value if you wanted.
Wonderfull! Thank you so much! Unfortunately, I can’t try to test this and modify this, because I’m not at home, but I can’t wait to try this! Thank you so much again!