7

I'm trying to figure out how Graphic.Raycaster works, but documentation doesn't help. I want to use it to cast raycast from some position at a certain angle and hit the UI. The other thing is that I don't know how to make it interact with the UI(drag, click etc.). I know that's broad subject, but I just can't find any good explanation of how to use it, so I would be grateful for any explanation.

bolov
  • 72,283
  • 15
  • 145
  • 224
Wojtek Wencel
  • 2,257
  • 6
  • 31
  • 65
  • have you read [this](http://answers.unity3d.com/questions/1202359/raycast-against-ui-in-world-space.html) ? – Uri Popov Aug 23 '16 at 07:30

2 Answers2

8

From Unity docs:

The Graphic Raycaster is used to raycast against a Canvas. The Raycaster looks at all Graphics on the canvas and determines if any of them have been hit.

You can use EventSystem.RaycastAll to raycast against graphics(UI) elements.

Here is a short example for your case:

void Update() {


// Example: get controller's current orientation:
  Quaternion ori = GvrController.Orientation;

  // If you want a vector that points in the direction of the controller
  // you can just multiply this quat by Vector3.forward:
  Vector3 vector = ori * Vector3.forward;

  // ...or you can just change the rotation of some entity on your scene
  // (e.g. the player's arm) to match the controller's orientation
  playerArmObject.transform.localRotation = ori;

  // Example: check if touchpad was just touched
  if (GvrController.TouchDown) {
    // Do something.
    // TouchDown is true for 1 frame after touchpad is touched.

    PointerEventData pointerData = new PointerEventData(EventSystem.current);

    pointerData.position = Input.mousePosition; // use the position from controller as start of raycast instead of mousePosition.

    List<RaycastResult> results = new List<RaycastResult>();
    EventSystem.current.RaycastAll(pointerData, results);

    if (results.Count > 0) {
         //WorldUI is my layer name
         if (results[0].gameObject.layer == LayerMask.NameToLayer("WorldUI")){ 
         string dbg = "Root Element: {0} \n GrandChild Element: {1}";
         Debug.Log(string.Format(dbg, results[results.Count-1].gameObject.name,results[0].gameObject.name));
         //Debug.Log("Root Element: "+results[results.Count-1].gameObject.name);
         //Debug.Log("GrandChild Element: "+results[0].gameObject.name);
          results.Clear();
     }
   }
}

The above script is not tested by myself. So there might be some errors.

Here are some other references to help you understand more:

  1. Graphics Raycaster of Unity; How does it work?
  2. Raycast against UI in world space
  3. How to raycast against uGUI objects from an arbitrary screen/canvas position
  4. How do you perform a Graphic Raycast?
  5. GraphicRaycaster

Hope it helps.

Community
  • 1
  • 1
Umair M
  • 10,298
  • 6
  • 42
  • 74
  • 1
    Thaks! I don't understand few things in your code. ` Vector3 vector = ori * Vector3.forward;` - I'm creating this vector, but it's never used again, so i have no idea how this script can work. Because of that the direction of the ray isn't set. – Wojtek Wencel Aug 23 '16 at 11:29
  • This code is from GVRController, so this vector can be used to raycast. Replace `Input.mousePosition` with this, and check if this works. – Umair M Aug 23 '16 at 11:50
  • 1
    I replaced it and it doesn't work also debug log message isn't displayed. – Wojtek Wencel Aug 23 '16 at 12:09
  • Try [Debug.DrawRay](https://docs.unity3d.com/ScriptReference/Debug.DrawRay.html) to check in scene view what direction is the vector pointing. – Umair M Aug 23 '16 at 12:13
  • Oh and yes, you need to remove the layer name check from code as well. Remove the inner if condition which is comparing layers – Umair M Aug 23 '16 at 12:15
  • 1
    I removed this layer check before, now when I'm drawing ray like this `Debug.DrawRay(transform.position, vector);` it's going through UI element. Maybe this doesn't works because `vector` is used as position, not as direction? – Wojtek Wencel Aug 23 '16 at 12:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/121618/discussion-between-umair-m-and-faken). – Umair M Aug 23 '16 at 12:26
  • 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. – kolboc Nov 27 '18 at 16:02
  • It uses all as the name suggests – Umair M Nov 27 '18 at 19:32
  • 'pointerData.position' is a Vector2D NOT 3D... so what is this value in VR? – zezba9000 Jul 27 '21 at 21:48
2

Umair M's current suggestion doesn't handle the fact that the ray is originating in world space and traveling at an angle.

It doesn't look to me like you can do a GUI raycast in world space at an angle even if your canvas is in world space. This page suggests a technique of creating a non-rendering camera, moving it around in 3D space with the ray you want to cast, and then doing the GUI raycast relative to that camera. I haven't tried it yet, but it sounds promising.