I want to be able to make an array, which has all the UI elements, under the cursor , inside the array. This is because I need to be able to tell if there is a UI element beneath multiple other UI elements, I've tried other techniques, but it only shows the UI element on top.
Edit: To be more clear, I am trying to make a list of all the pieces of UI that are layered beneath the cursor, and not only being able to tell which UI is on the top.
Sounds like you are looking for UI.GraphicRaycaster.Raycast.
The GraphicRaycaster is usually attached to each Canvas (otherwise you wouldn't be able to interact with anything in them).
So without referencing a specific canvas you could just go and get them all:
// Because this is dynamically changing I recommend to stick to a List instead of an array
private List<RaycastResult> _hits = new List<RaycastResult>();
private EventSystem _eventSystem;
private void Awake()
{
//Fetch the Event System from the Scene
_eventSystem = FindObjectOfType<EventSystem>();
}
private void Update()
{
//Check if the left Mouse button is clicked
if (Input.GetKeyDown(KeyCode.Mouse0))
{
//Set up the new Pointer Event
var eventData = new PointerEventData(_eventSystem) {position = Input.mousePosition};
//Create a list of Raycast Results
_hits.Clear();
// Get all existing graphicsRaycaster
// NOTE: Of course you should rather cache this result e.g. in Awake
// and only update it if a Canvas is added to or removed from the scene
var graphicsRaycasters = FindObjectsOfType<GraphicRaycaster>();
foreach(var graphicsRaycaster in graphicsRaycasters)
{
graphicsRaycaster.Raycast(eventData, _hits);
}
// Do something with the hits
foreach (var result in _hits)
{
Debug.Log(result.gameObject.name, result.gameObject);
}
}
}
Render mode screen space overlay will always render ui in front. One way to achieve gameobject in front of ui is to change the camera render mode to screen space camera so that you can use sprite with with higher negative z value position in front of ui.
or you can use GraphicRaycaster
To make a raycast tooltip list by name:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
using System.Linq;
public class UI : MonoBehaviour
{
private GraphicRaycaster rc;
private PointerEventData pt;
EventSystem eventSystem;
public TMP_Text text;
public List<RaycastResult> results;
private void Start()
{
//initialize
rc = GetComponent<GraphicRaycaster>();
eventSystem = GetComponent<EventSystem>();
pt = new PointerEventData(eventSystem);
results = new List<RaycastResult>();
}
private void Update()
{
//get screen mouse position
pt.position = Input.mousePosition;
results.Clear();
rc.Raycast(pt, results);
if (results.Count > 0)
{
//enable tooltip
text.gameObject.SetActive(true);
text.transform.position = pt.position;
//reset text if results.count change
text.text = "";
foreach (RaycastResult res in results)
{
text.text += res.gameObject.name + "\n";
}
}
else
{
text.gameObject.SetActive(false);
text.text = "";
}
}
}
make text mesh pro anchored on top left
