Teleportation in VR with Google Daydream

vr-nyan

Of all the complexities involved with building VR applications designing locomotion is possibly the most difficult. Representing natural movement through virtual worlds is made complicated by VR’s inability to track bodies outside of a small localized area. The problem is not dissimilar to the Exactitude In Science paradox discussed by the French philosopher (and grandfather of Simulation Theory) Jean Baudrillard. In his book Simulacra and Simulation Baudrillard, referencing Borges, discusses accuracy of representation through the dilemma of a great empire that creates a map so detailed that it covers the entire empire itself. This paradox similarly describes the problem with representing movement in VR. It is not possible to perfectly track the free movement of a user without having a physical system that is of equal size to the simulated VR environment – a map the size of the empire. In light of this obstacle various creative solutions have arisen, one of which happens to be the topic of discussion in this post, teleportation. The teleportation model removes the need for bipedal locomotion by instantly transporting a user to any location they wish to visit. In our case a simple point and click mechanism forms the basis of the interaction model.

Update (01/08/17): This tutorial was originally written using a pre-release version of the Daydream Unity SDK. The code in the tut is still totally valid, but the linked Unity package uses an older SDK so may not run in newer versions of Unity. See my updated tutorials here on setting up Daydream and here on building a working controller based app with teleportation that uses the release SDK.

Movement In VR Space
To understand locomotion in VR space it is important to first understand some standard terminology. Two common concepts unique to VR movement can be grouped under the term: Degrees of Freedom. Where Three Degrees of Freedom, or 3 DoF, describes the free rotation of a head mounted display on a fixed axis  (x, y ,z). While Six Degrees of Freedom, or 6 DoF, adds positional movement within a three dimensional space to the 3 DoF model (x, y, z rotation and translation). Google Daydream Viewer, Cardboard and Samsung Gear VR are examples of 3 DoF headsets, while the HTC Vive creates a 6 DoF environment.

Over time these patterns will calcify and models for tackling this problem will become standards. Until then it’s an exciting time to be experimenting with new (and unusual) methods of “hyperlinking” bodies around the VR universe. As far as locomotion in VR is concerned the future is yet to be designed.

 

 

The Code
To instigate teleportation the user simply points at a location, clicks and they’re magically transported. You can download the finished Unity package and start playing around with it here. The core of this code is built on top of my previous laser pointer tutorial with an added teleportation component. We pass in a gameObject called redTarget that acts as the destination target for the teleportation location (line 6). We also pass in a reference to the user’s camera, so we can move it to the teleported location. Firing a Raycast (lines 38 – 41) on the ground allows us to update the x, z position of the target to the laser’s location while keeping the y pos consistent. When a touch down is registered (lines 28-32) we teleport the camera object to the new location. The rest of the code relates to drawing the laser and is covered in my previous tutorial.

using UnityEngine;
using System.Collections;

public class ControllerManagerScript : MonoBehaviour {

	public LineRenderer laser;
	public GameObject redTarget;
	public Camera mainCam;

	Vector3 currentTargetPos;

	void Start () {
		Vector3[] initLaserPositions = new Vector3[ 2 ] { Vector3.zero, Vector3.zero };
		laser.SetPositions( initLaserPositions );
		laser.SetWidth( 0.01f, 0.01f );
	}
	
	void Update () {
		Quaternion ori = GvrController.Orientation;
		gameObject.transform.localRotation = ori;

		Vector3 v = GvrController.Orientation * Vector3.forward;

		ShootLaserFromTargetPosition( transform.position, v, 200f );
		laser.enabled = true;

		if (GvrController.ClickButtonUp) {
		    // teleport to location
		    Vector3 pointerTeleportPos = new Vector3 (currentTargetPos.x - 0.46f, 0.81f, currentTargetPos.z + 1.3f);
		    gameObject.transform.position = pointerTeleportPos;
		    Vector3 camTeleportPos = new Vector3 (currentTargetPos.x , 1.6f, currentTargetPos.z);
		    mainCam.transform.position = camTeleportPos;
		}
	}

	void ShootLaserFromTargetPosition( Vector3 targetPosition, Vector3 direction, float length )
	{
		Ray ray = new Ray( targetPosition, direction );
		RaycastHit raycastHit;

		if( Physics.Raycast( ray, out raycastHit, length ) ) {
	            GameObject gameObj = raycastHit.transform.gameObject;
		    if (gameObj.tag == "GroundTag") {
		        // Show the target and follow track to the pointer
			currentTargetPos = new Vector3 (raycastHit.point.x,
				                        redTarget.transform.localPosition.y,
				                        raycastHit.point.z);
			redTarget.transform.localPosition = currentTargetPos;
		    }
		}

		Vector3 endPosition = targetPosition + ( length * direction );
		laser.SetPosition( 0, targetPosition );
		laser.SetPosition( 1, endPosition );
	}
}

In this article we’ve covered a simple teleportation technique for easily traveling distances by point and click. This method of teleportation is pretty straight forward, the user directs a pointer to a location and then we teleport them there. A simple addition to add some polish would be to add a slight arc to the curvature of the laser pointer line. Also a quick blink effect with a fade out and in would visually denote the change in location clearly.

Disclaimer: I’m a Google employee and write blog posts like this with the sole purpose of encouraging and inspiring developers to start exploring Google’s amazing Daydream VR platform. Opinions expressed in this post are my own and do not reflect those of my employer. I would never share any secret or proprietary information.

10 comments

  1. Your posts have been great for getting comfortable with Daydream development. To expand on teleportation, I’ve taken the hammer set-up from the Xylophone sample from the ControllerPlayground project so that the controller rotates properly with turning your head/body in gameplay.

    I’ve run into an issue with getting this elbow-rigged set-up to teleport with the GVRCarboardMain. Have you been able to achieve teleportation in all directions?

    Reply

      1. I was able to get the functionality by destroying and instantiating the elbow-rigged ControllerObject when teleporting. Maybe this is similar to your solution? Though I suppose I’ll see in the next post! It seems a bit hacky, but it works as I hoped it would. Looking forward to the future posts.

        Reply

        1. @Sawyer, I’ll be posting a new tut on teleportation in all directions with the rotating elbow model later this week, time permitting 🙂

          Reply

  2. I LOVE the GIF at the top of this. That was one of the things I planned on making in VR. I want to ride Nyan cat around through space playing some sort of awesome mini game. Thanks again for these awesome tutorials.

    Reply

  3. Instead of a discontinuous translation you should consider a quick continuous translation that adds a small amount of optical flow before a teleport. My research lab recently did a user study that found that such a teleportation mechanism doesn’t increase cybersickness but the optical flow does allow for path integration (e.g. estimating how much distance is travelled), which then significantly reduces spatial disorientation. Contact me if you want me to send you our paper.

    Reply

    1. @Eelke Folmer, thanks for the comment! Would love to read your paper, maybe you can post the link here so everyone can check it out. I totally agree RE the discontinuous transitions. Most of my tutorials should be seen as intros to get people up and running quickly with the SDK, as opposed to final polished implementations, or best practices for software architecture. Although I try to create a good starting point for both of these.

      Reply

Leave a Reply to Sawyer Cancel reply

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