Google Cardboard: Set rotation of head?

Alright, I’ve tried everything but I’m creating a VR app using Google Cardboard and I’m trying to set the rotation of the head object. I am able to print the rotation of the Head object to the console by printing head1.transform.localRotationand getting the Head object using public CardboardHead head1; however unlike other objects, I am not able to CHANGE this rotation.

I realize that the CardboardHead script continuously overrides and sets the rotation of the Head object here:

if (trackRotation) {
      var rot = Cardboard.SDK.HeadPose.Orientation;
      if (target == null) {
        transform.localRotation = rot;

      } else {
        transform.rotation = target.rotation * rot;
      }
    }

And I have even tried to alter these values however I just want to alter the rotation of the head object temporarily so that the Head object “snaps” to a certain rotation after the round is over in my game (after that if they turn their head the Head object turns like normal)

I just want to make the player “look” somewhere (I want them to face a canvas) but when I try to alter the Head object’s rotation like this:

head1.transform.rotation = new Quaternion(0.0f,0.0f,0.0f,0.0f);

or

head1.transform.localRotation = new Quaternion(0.0f,90.0f,70.0f,80.0f);

Nothing happens. The Head object remains in the rotation it initially set which seems to be (1.0,0.0,0.0,1.0). Why is this? How can I change the Head rotation?

Managed to do it by adding a parent object to the camera.
While you will have no luck performing rotations on the “main camera”, if you create a game object as a parent, and rotate that, then camera gets rotated as well.

In other words, just create a “head” parent for the main camera and rotate that instead

It seems to be impossible. I noticed this a couple of days ago. The cardboard script will override any change in rotation you throw at it, and for good reason: they want the user to have full control. Here is a piece of Google’s Cardboard Design overview:

“It is important that users are not “passengers” in the app as much as active drivers. Users should remain in control of their movement inside the app, so that they will be able to actively anticipate what they are about to see.”

You may have good reason to override it, but Google doesn’t seem to think so. There is a workaround however; rotate the entire scene!

It may sound crazy, but really that’s what every game engine does anyways. There is no literal “camera” object in games; the scene is just panned, rotated, and scaled to simulate what the scene would look like had there been actual camera in a specific spot.

I’m in the same boat you’re in; I would pause my Cardboard game, and the user would not be facing the pause menu. The first helpful tip is to always put canvases on either side (front and back) of the user for greater flexibility. Secondly, here is what I plan on doing:

As you said, you can read Cardboard’s rotation, but you cant write it, so what I do is, I constantly read Cardboard’s rotation while the game is playing, and when the game is paused, I stop reading it. That way, I have reference to the last rotation. Note that for this to work, the entire scene has to be the child of an empty placed in the middle of the scene, with the Cardboard object being the only object outside of this hierarchy. Also,the empty does not have to be in the middle, but the Cardboard and empty must be located in the same position when paused (I simply move Cardboard to the middle when paused, and move it back when unpaused). Then, since the default y rotation of the pause menu is 0, I take the y of the last rotation, and I rotate the game world by the same amount. So if the player is rotated 45 degrees, rotate the empty containing the entire scene by 45 degrees. You can do this on all axis, but in the case of UI, I recommend you only do this on the y axis. This has an added benefit; now you only have to align the empty and Cardboard on the y axis for this to work. Finally, when the game is unpaused, I reset the rotation of the empty, and everything goes back to normal.

Realize that we may not be in the exact same situation, but I believe there is enough good information here for you to craft your own solution, if this one isn’t tailored enough to your needs. I hope this enough, and good luck on your game!

Just as eyals was saying, create an empty GameObject and make your main camera a child of this. Then place the scripts to change rotation in this empty GameObject. I wanted to change set the initial rotation value, so I added this StartRotation.cs script onto the parent

public class StartRotation : MonoBehaviour {
	public Vector3 startRot; 

	void Start () {
		Quaternion startQ = Quaternion.Euler(startRot);
		transform.rotation = startQ;
	}

}

Hope this helps anyone wanting to change their rotation value at the start.

I seriously recommend you change the best answer to @eyals response.

You really only need to create a parent object to house the main camera. The main camera will then inherit the parent’s transform - something you can manipulate directly with a script on start.

This solution works perfectly and is not nearly as complicated as @Jjules response.

This question is a bit old but for Google VR SDK 1.50+ (Unity 5.6) you can do

transform.eulerAngles = new Vector3(newRot.x, newRot.y, newRot.z);
UnityEngine.VR.InputTracking.Recenter();

also, if you don’t want to get confused you also need to catch the GvrEditorEmulator instance and Recenter it as well.

#if UNITY_EDITOR
        gvrEditorEmulator.Recenter();
#endif

Recentering GvrEditorEmulator though doesn’t seem to work very well at the moment but if you disable it you’ll see the recentering works for the main camera.