Is it possible to raycast onto a canvas Image component? My Image components have “Raycast Target” checked on.
I’m NOT raycasting from a mouse position, but rather based on a different game objects position (raycasting from a different rectTransform that lives within the same canvas).
My current canvas is in Render Mode ‘Screen Space - Camera’, but I could also do a world space canvas if needed.
FWIW -I want to avoid adding box colliders to each canvas element. Then there’s the whole z-depth issue for raycasting w/ multiple overlapping box colliders which becomes messy very quickly.
Thanks. Ended up doing the following to get it working:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class MyVirtualCursor : MonoBehaviour
{
[SerializeField] GraphicRaycaster m_Raycaster;
PointerEventData m_PointerEventData;
[SerializeField] EventSystem m_EventSystem;
[SerializeField] RectTransform canvasRect;
void Update()
{
//Set up the new Pointer Event
m_PointerEventData = new PointerEventData(m_EventSystem);
//Set the Pointer Event Position to that of the game object
m_PointerEventData.position = this.transform.localPosition;
//Create a list of Raycast Results
List<RaycastResult> results = new List<RaycastResult>();
//Raycast using the Graphics Raycaster and mouse click position
m_Raycaster.Raycast(m_PointerEventData, results);
if(results.Count > 0) Debug.Log("Hit " + results[0].gameObject.name);
}
}
Try to replace m_PointerEventData.position = this.transform.localPosition; with m_PointerEventData.position = Input.mousePosition;, then it will try to get what you hit “at the mouse position”.
The original code tried to get hits where the attached transform is, which means, whatever it was “on top of”, I believe that’s why you guys were unable to get any results.
You’re a hero. I have been stuck trying to use the GraphicsRaycaster for over 24 hours now and that simple comment is all it took to get it working. You, my friend, are better than the NON-EXISTANT documentation on the eventsystem library.
i wanna navigate player if user touches the screen then raycasting from pointer and navigation stuffs. by i have an essue that then he touches buttons like pause button he moves around .
It’s working alright, modified it to work for me, however, I noticed that EventSystem.current.RaycastAll is quite slow and causes pretty big allocations when used many times in a frame.
Thanks a lot, it worked like a charm
I used this in an AR App and just had to pass a
“new Vector2(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y”
To the “PointerIsOverUI” to know if we have touched a UI element or not
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
// using this for mouse clicking on Disable UI to add popup for Mobile since there is no Mouse over functionality on touch screen
[RequireComponent(typeof(Button))]
public class UIAddToolTip : MonoBehaviour
{
private Button button;
public GameObject UI_MouseOverToolTip;
private void Start()
{
button = This.GameObject.GetComponent<Button>();
}
private void Update()
{
if (button.IsInteractable() == false)
{
if (Input.GetButtonUp("Fire1"))
{
bool isPointOVerThis = RaycastUtilities.PointerIsOverUI(Input.mousePosition, this.gameObject);
if (isPointOVerThis)
{
Debug.Log("Pointer is OVer disabled UI");
UI_MouseOverToolTip.SetActive(true);
//add code to populate the UI ToolTip with needed info
}
}
}
}
}
//added a check to see if this button was hit with raycast
public static class RaycastUtilities
{
public static bool PointerIsOverUI(Vector2 screenPos, GameObject GO)
{
var hitObject = UIRaycast(ScreenPosToPointerData(screenPos));
return hitObject != null && hitObject.layer == LayerMask.NameToLayer("UI") && hitObject == GO;
}
public static GameObject UIRaycast(PointerEventData pointerData)
{
var results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerData, results);
Debug.Log(results[0].gameObject.name + "Was raycast hit...");
return results.Count < 1 ? null : results[0].gameObject;
}
static PointerEventData ScreenPosToPointerData(Vector2 screenPos)
=> new(EventSystem.current) { position = screenPos };
}
using this for mouse clicking on Disable UI to add popup for Mobile since there is no Mouse over functionality on touch screen