- Home /
(Unity 4.6) How to raycast against uGUI objects from an arbitrary screen/canvas position
We wanted to do a raycast from an arbitrary position over uGUI objects. As far as we can tell, we seem to need an instance of GraphicRaycaster. As one comes attached to the default Canvas object, we could easily get its reference (let's call it "raycaster") and then call raycaster.Raycast(...).
Now, Raycast receives two arguments: a PointerEventData (common event object to all mouse/touch events) and a List. Currently, the documentation for Raycast does not describe what it does exactly, but we assume that the List of RaycastResults is filled by Raycast itself. From each RaycastResult we could then access the gameObject it hit (it's documented here).
But what about PointerEventData? Isn't it supposed to come from a pointer event? Here, we have no mouse or touch, and simply want to raycast from an arbitrary position. How should we proceed to create one and set its (screen/world) position? Or is there another way for uGUI raycasts altogether?
Answer by CanisLupus · Nov 21, 2014 at 11:46 PM
It turns out that simply creating a new PointerEventData and then setting its position to wherever you want (in 2D) works. For instance, in the following example I raycast from someWorldPosition, getting a list of the uGUI elements that are behind that screen point.
var pointer = new PointerEventData(EventSystem.current);
// convert to a 2D position
pointer.position = someCamera.WorldToScreenPoint(someWorldPosition);
var raycastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointer, raycastResults);
if (raycastResults.Count > 0) {
// Do anything to the hit objects. Here, I simply disable the first one.
raycastResults[0].gameObject.SetActive(false);
}
Thanks! Had no idea it was that simple. The new UI is quite different how it works. :D
I wanted to make my icons follow the mouse cursor (for inventory) so this is my version of the above, on mouse button, in C#.
if(Input.Get$$anonymous$$ouseButton(0))
{
PointerEventData pointer = new PointerEventData(EventSystem.current);
pointer.position = Input.mousePosition;
List<RaycastResult> raycastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointer, raycastResults);
if(raycastResults.Count > 0)
{
if(raycastResults[0].gameObject.tag == "InventoryItem")
raycastResults[0].gameObject.transform.position = Input.mousePosition;
}
}
EDIT: Don't forget to add "using UnityEngine.EventSystems;" at the top, and ofc "using System.Collections.Generic;" for lists.
Hello people,this is exactly solution to save my life/game but i can't translate this into java.
i can do only fist line :
var pointer : PointerEventData; pointer = new PointerEventData(EventSystem.current);
Any help is appreciated.
Hey I have a question about RaycastAll. Is it raycasting just against UI elements or it does take into considerations other raycasts (ex. Physics Raycaster) too ? I'm asking because the documentation states that EventSystem by default has 3 raycasters if I read and understood it well.
Answer by Bitpocketer · Feb 06, 2016 at 12:48 PM
One thing i would like to know though, how one would make the associated button with the pointer send the submit event to the eventsystem?
Your answer