How to use Graphic Raycaster with WorldSpace UI?

2019-02-25 12:37发布

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 an certain angle and hit UI. The other thing is that I don't know how to make it interact with UI(drag, click etc.). I know that's broad subject, but I just can't find any good explanation of what it actually is and how to use it, so I would be grateful for any explanation.

标签: unity3d
2条回答
We Are One
2楼-- · 2019-02-25 12:45

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.

查看更多
做个烂人
3楼-- · 2019-02-25 13:10

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.

查看更多
登录 后发表回答