Daydream VR: Raycast Data From the GvrBasePointer Without an EventTrigger

This is a quick and easy technique for extracting data from the GvrLaserPointerImpl’s raycast system without going through the GvrPointerInput system or the targetObject’s TriggerEvent. Using the Player gameObject pattern of my previous tutorials or the same pattern from the Daydream SDK demos you can use this method to easily make a teleportation system with all code contained within the Player. No need to add an EventTrigger on the targetObject. Using the GvrPointerManager singleton class we can access the GvrLaserPointerImp, extract the PointerIntersection Vector3 data and use this to move the Player around. The Gist here.

using UnityEngine;
using UnityEngine.UI;

public class PlayerController : MonoBehaviour {

	void Update () {
		if (GvrController.ClickButtonUp) {
			GvrLaserPointerImpl laserPointerImpl = (GvrLaserPointerImpl)GvrPointerManager.Pointer;
			if (laserPointerImpl.IsPointerIntersecting) {
				gameObject.transform.position = new Vector3(laserPointerImpl.PointerIntersection.x, gameObject.transform.position.y, laserPointerImpl.PointerIntersection.z);
			}
		}
	}
}

12 comments

  1. Hi Sam,
    I don’t get it, you attach this script to the player? and then it should work? How do i hook this up?

    In the end i want to be able to pick up objects, any idea of how to do that?

    Reply

    1. @popman24 Thanks for the comment! Yes you can attach this script to the Player, but if you’re currently using an EventTrigger on the “selection” object I’d remove it. I was looking for a way to get positional data of the reticle on the Gvr Raycast’s hit object without having to attach an EventTrigger to the hit object. This way everything’s nicely contained inside the Player, and a message doesn’t need to be sent back from the EventTrigger’s PointerClick method to the Player to get the data. You don’t have to use this method and it definitely isn’t the best solution for every scenario but I thought people might find it useful as a possible option. If you find it confusing I’d recommend going through my previous tutorial on creating a Daydream app with a controller and look at how I’m doing the teleportation by attaching an EventTrigger to the ground that in turn fires a method to update the Player’s position. Picking up objects would be very similar to this although instead of clicking the ground and moving the player, on TouchDown you want to get the reticle’s intersectional position with the object in 3D space via the raycast, and then continue moving your object to that point until the controller’s TouchUp is triggered. It’s an interesting mechanic, I’ll write a tutorial for it when I get a chance. Hope that helps.

      Reply

      1. Hi Sam,
        Thanks so much for your answer! With help it’s working now! if you’re making a tutorial about it, please consider including how to move the pickedup object through space so you can place it wherever you. I was thinking of doing that with the touchpad so sliding ‘up’ on the touchpad would make the object move further away and sliding ‘down’ would make the object move closer. I’m looking forward to more tutorials! Your tutorials have been of great help!
        Sander

        Reply

  2. Hey Sam,

    this is great. I’m really enjoying your Daydream tutorials.

    Any thoughts on how I would get this to work on a Terrain, where the y teleportation point is variable? For SteamVR I use something like this to work out the y teleportation co-ordinate:

    if (target.GetComponent()) {
    var terrainHeight = Terrain.activeTerrain.SampleHeight(hitInfo.point);
    float y = (terrainHeight > hitInfo.point.y) ? hitInfo.point.y : terrainHeight;
    cameraRig.transform.position = new Vector3(hitInfo.point.x, y, hitInfo.point.z);
    }

    So I guess I’m really asking is laserPointerImpl.PointerIntersection.y the same as the hitInfo.point from a Raycast Hit?

    Reply

    1. Actually what I’m really asking is there any way to get hitinfo from GvrLaserPointerImpl laserPointerImpl? I’m building a game where I need to know what object I’m hitting with the Controller raycast….

      Reply

      1. To get the hitinfo from GvrLaserPointerImpl, I referred the google vr docs and found out that all inputs for a physics.raycast query are available in this implementation.
        So, what I did is this in the Update method:
        laserpointerimpl = (GvrLaserPointerImpl)GvrPointerManager.Pointer;
        Ray ray = laserpointerimpl.PointerIntersectionRay;
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 100)) {
        objectDetected = hit.collider.gameObject;
        }

        Simply add the collider to the object you want to detect and you’re good to go…

        Reply

  3. @Andrew It is possible to get the y pos, if you see my example I’m hard coding the y-pos of the gameObject so that the height stays the same, but for terrain, you could use: laserPointerImpl.PointerIntersection.y and then add an offset for the camera.
    The target GameObject data isn’t publicly exposed in GvrLaserPointerImpl but it is there. If you take a look at the onPointer event arguments (line 89) there’s a “targetObject”. That’s what you want. It’s not being handled in any way so you could either update the class and save that variable, but that starts to become a bit hacky, or you could extend the class and override those methods and handle the targetObject GameObject that way. Probably the better way to do it and the recommendation in the header of the GvrPointerInputModule class is to add an EventTrigger (and collider) to the object you want to intersect with and get the PointerEventData and the gameObject from there. This follows a similar pattern to my previous tutorials.

    Reply

    1. Thanks Sam,

      That’s getting a bit beyond my current C# level, but I’ll try play around with extending the GvrLaserPointerImpl to somehow extract the targetGameObject from OnPointerEnter on line 89. I need to know if the Object I’m hitting is the ground, another player etc from within the PlayerController script (if I add an event trigger to the object I want to intersect with its going to get messy in a multiplayer game).

      Thanks again and keep up the great blog!

      Reply

  4. Hey Sam,

    Unfortunately for teleporting at varying y values, laserPointerImpl.PointerIntersection.y and then add an offset for the camera doesn’t work. As soon as the laserPointerImpl.PointerIntersection.y is greater than zero you start lifting off the ground and moving further into the sky with every teleport?

    Reply

  5. Finally, I am able to pick up and throw objects using daydream controller while using the GvrLaserPointerImpl and without using the Event triggers on grabable objects!

    Reply

    1. @Sanket Could you post your code perhaps? I can’t get object grabbing to work using the method you described? I have colliders on each of my objects but for some reason the controller click isn’t being detected

      Reply

  6. Since I’ve come across this post a few times while searching for an answer, I’m gonna leave this here. I wasn’t able to get this code working with the current version of the sdk, but after some tweaking I believe this is currently the way to access the raycast data:

    GvrBasePointer basePointer = (GvrBasePointer)GvrPointerInputModule.Pointer;
    if (basePointer.CurrentRaycastResult.gameObject != null) {
    Vector3 pos = basePointer.CurrentRaycastResult.worldPosition;
    }

    Reply

Leave a Reply to popman24 Cancel reply

Your email address will not be published. Required fields are marked *