Best way to click on a object behind other

Hi.
This is a bit more general question.

I made a quick illustration about my problem

And my question is:
what would be the best way to ensure that when I click on any of those objects coloured area, then that object actually gets clicked/hit, even if it actually is behind other objects.
Basically all the objects are simple plane meshes with some textures on them. The textures are transparent where theres no colour.
So for example in my illustration if I would click in the marked point I would like the green sphere to get selected, but the problem is that it lays behind both of the other objects mesh/collider, so actually the red cross would get selected.

Now I did some research and there seem to be some solutions out there that detect if the hit point pixel is transparent or not.
For example this one but Im worried that even if I could detect that I clicked on the transparent part of Object Z1 then I wouldn’t know how to make the ray keep going until it hits a actual pixel. Another thought I had was to make custom meshes or even only collider meshes for each of the object’s, but that seems a lot of manual labor.

So in conclusion should I go with:

  • a) Detecting pixel alphas
  • b) Custom meshes for each object
  • c) Something totally different
    ???

Any guidance much appreciated!

Sry if too long for Answers.

Thought I’ll share my final code I got working.

using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using System;
public class AlphaTest : MonoBehaviour {
	
	private RaycastHit[] hits;
	private Ray ray;
	Camera myCam;
	private GameObject selectedPlayer = null;
	List<GameObject> disabledGameobjects = new List<GameObject>();
	List<RaycastResult> hitList = new List<RaycastResult>();
	
	// Use this for initialization
	void Start () {
	myCam=Camera.main;
	}
	
	
	public class RaycastResult: IComparable<RaycastResult>
	{
	    public float distance;
	    public Collider collider;
		public Vector2 textureCoord;
	    public RaycastResult(RaycastHit hit)
	    {
	        distance = hit.distance;
	        collider = hit.collider;
			textureCoord = hit.textureCoord;
	    }
	 
	    public int CompareTo(RaycastResult other)
	    {
	        return distance.CompareTo(other.distance);
	    }
	}
	
	void SortDistances()
	{
	    hitList.Clear();
	    hits= Physics.RaycastAll(ray);
	 
	    foreach(RaycastHit hit in hits)
	    {
	        hitList.Add(new RaycastResult(hit));
	    }
		hitList.Sort();
	}
	
    void Update() {
		ray = myCam.ScreenPointToRay(Input.mousePosition);
		//When mouse left button is pressed down | This Fires only once
        if(Input.GetMouseButtonDown(0)){
			SortDistances();
			
			Debug.Log("HIT-----------------------------");
			foreach(RaycastHit hit in hits){
				Debug.Log(hit.collider.name+""+hit.distance);
				
			}
			Debug.Log("LIST-----------------------------");
			foreach(RaycastResult listItem in hitList){
				Debug.Log(listItem.distance);
			}
			
			
				for(int i=0;i<hitList.Count;i++)
				{	
					
					if(hitList*.collider.tag=="Player")*
  •  			{*
    

_ selectedPlayer = hitList*.collider.transform.gameObject;*_

_ Renderer renderer = hitList*.collider.renderer;
MeshCollider meshCollider = hitList.collider as MeshCollider;
if (renderer == null || renderer.sharedMaterial == null || renderer.sharedMaterial.mainTexture == null || meshCollider == null)
return;*_

* Texture2D texture = renderer.material.mainTexture as Texture2D;*
_ Vector2 pixelUV = hitList*.textureCoord;*
pixelUV.x *= texture.width;
pixelUV.y *= texture.height;_

* Color pixel = texture.GetPixel((int)pixelUV.x, (int)pixelUV.y);*
* //Debug.Log(pixel.a);*
* if(pixel.a < 1){*
* //We hit a transparent pixel*
* selectedPlayer.renderer.material.color = Color.black;*
* selectedPlayer.collider.enabled=false;*
* disabledGameobjects.Add(selectedPlayer);*
* }*
* else if(pixel.a >= 1){*
* //We did not hit a transparent pixel*
* selectedPlayer.renderer.material.color = Color.white;*
* //Debug.Log(selectedPlayer.name);*
* return;*
* }*

* }*

* } *

* }*
* //While mouse left button is held down| This Fires every frame*
* if(Input.GetMouseButton(0)){*

* }*
* //When mouse left button is released | This Fires only once*
* if(Input.GetMouseButtonUp(0)){*
* foreach(GameObject disabledGameobject in disabledGameobjects){*
* disabledGameobject.collider.enabled=true;*
* disabledGameobject.renderer.material.color=Color.white;*
* }*
* disabledGameobjects.Clear();*

* }*

}

}
A couple of notes. All the textures have to have Read/Write enabled and a compression format that allows alpha.For example RGBA 32 bit Also this code works only with Meshcolliders. I’m also using a IComparable to order RaycastAll results. It could be done with Linq but I had problems with Linq on IOS.
Anyway hope somebody finds this useful.

You can use RaycastHit.textureCoord to get the UV coordinates of the texture at the point you hit the object. Then you need to use Texture2D.GetPixel, and check that pixel’s alpha value. If the alpha value is near zero (or below a transparency threshold), temporarily disable that object’s collider and do another identical raycast, repeating the process until you hit something or the raycast returns false. Don’t forget to re-enable the colliders once everything is finished.