Raycasting through UI Image with transparent part


I use the new UI system (on unity 5.2.2) and I have an UI Image that contains a 2D sprite.
This sprite have some transparent parts and looks like this : 58836-sans-titre.png

(in gray transparent parts, in orange colored parts)

I use Physics.Raycast to select my gamesObjects in the scene and I check if my pointer isn’t on a UI element (with EventSystem).
But my problem is that EventSystem.IsPointerOverGameObject() return true on gray (transparent) parts of my sprite.How can I select 3D elements through transparent parts of my UI elements.

Thanks for help.

some code :

if (Input.GetButtonDown("Mouse1"))
   if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out selectionRay) &&
       Debug.Log("Select game object "+ selectionRay.collider);

Resurrecting as this is a top google hit…
use this:

GetComponent<Image>().alphaHitTestMinimumThreshold = 1f; // or anything > 0


Here is the solution: use RaycastAll to retrieve all the objects hit, then return the closest object such that the alpha value of the pixel is not 0.

private static RaycastHit? RaycastWithTransparency(Ray ray)

    var res = Physics.RaycastAll(ray, float.MaxValue).ToList().OrderBy(h => h.distance);

    foreach (var h in res)
        var col = h.collider;

        Renderer rend = h.transform.GetComponent<Renderer>();
        Texture2D tex = rend.material.mainTexture as Texture2D;
        var xInTex = (int) (h.textureCoord.x*tex.width);
        var yInTex = (int) (h.textureCoord.y*tex.height);
        var pix = tex.GetPixel(xInTex, yInTex);

        if (pix.a > 0)
            //Debug.Log("You hit: " + col.name + " position " + h.textureCoord.x + " , " + h.textureCoord.y);
            return h;
    return null;

Using Physics.RaycastAll does not work with UI since they dont have colliders and EventSystem.current.RaycastAll is used

How can you determine the transparency this way?


Script for RawImages that acts like alphaHitTestMinimumThreshold :

using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

 * RawImage doesn't have alphaHitTestMinimumThreshold, (which let's you avoid raycasting transparent pixels)
 * This class act's as alphaHitTestMinimumThreshold replacement for RawImages by overriding raycast's default behaviour
 * Stolen from https://github.com/Hengle/GrassWateringSimulator2019/blob/master/Grass%20Watering%20Simulator%202019/Assets/HTC.UnityPlugin/ViveInputUtility/Examples/4.Teleport/Scripts/ImageAlphaRaycastFilter.cs

public class ImageAlphaRaycastFilter : UIBehaviour, ICanvasRaycastFilter
    private RawImage m_rawImage;

    public float alphaHitTestMinimumThreshold = 1;

    protected RawImage rawImage {
        get { return m_rawImage ?? (m_rawImage = GetComponent<RawImage>()); }

    public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) {
        if (alphaHitTestMinimumThreshold <= 0) { return true; }
        if (alphaHitTestMinimumThreshold > 1) { return false; }

        var texture = rawImage.mainTexture as Texture2D;

        Vector2 local;
        if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rawImage.rectTransform, screenPoint, eventCamera, out local)) {
            return false;

        var rect = rawImage.GetPixelAdjustedRect();

        // Convert to have lower left corner as reference point.
        local.x += rawImage.rectTransform.pivot.x * rect.width;
        local.y += rawImage.rectTransform.pivot.y * rect.height;

        // normalize
        local = new Vector2(local.x / rect.width, local.y / rect.height);

        try {
            return texture.GetPixelBilinear(local.x, local.y).a >= alphaHitTestMinimumThreshold;
        } catch (UnityException e) {
            Debug.LogError("Using alphaHitTestMinimumThreshold greater than 0 on Graphic whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this);
            return true;