Reputation: 1
I have developed a VR game using Unity and Google VR SDK for Android. I want the game to be playable without a VR headset too. How should I implement switching from VR to Normal mode and vice versa? I want to maintain 360 rotation while in Normal Mode using the phone gyroscope. I have looked through many scripts online, but I can't find anything that would make this possible.
I have found that switching modes can be done using XRSettings.enabled = true/false (depending on the mode), but how to maintain 360 rotation while in Normal (Non VR mode)
Here is the script I wrote:
public class GyroToggleManager : MonoBehaviour {
private int flag = 0;
private Quaternion offset;
IEnumerator SwitchToVR() {
string desiredDevice = "cardboard";
XRSettings.LoadDeviceByName(desiredDevice);
yield return null;
XRSettings.enabled = true;
transform.localRotation = Quaternion.identity;
}
IEnumerator SwitchTo2D() {
Input.gyro.enabled = true;
// couldn't figure out how to find this.
offset = ;
XRSettings.LoadDeviceByName("");
yield return null;
transform.localRotation = Quaternion.identity;
}
// Use this for initialization
void Start () {
if(XRSettings.enabled == false){
Input.gyro.enabled = true;
}
}
// Update is called once per frame
void Update () {
if (XRSettings.enabled) {
return;
}
//Also tried different combinations here nothing worked.
transform.localRotation = Input.gyro.attitude ;
}
public void StartVR(){
if(XRSettings.enabled == false){
StartCoroutine (SwitchToVR ());
}
}
public void StartN(){
if(XRSettings.enabled == true){
StartCoroutine(SwitchTo2D());
}
}
}
Updated Script:
public class GyroToggleManager : MonoBehaviour {
Quaternion offset;
IEnumerator SwitchToVR() {
string desiredDevice = "cardboard";
XRSettings.LoadDeviceByName(desiredDevice);
yield return null;
XRSettings.enabled = true;
transform.rotation = Quaternion.identity;
}
IEnumerator SwitchTo2D()
{
Input.gyro.enabled = true;
//Get offset.. Subtract Camera rotation from Gyro rotation
offset = transform.rotation * Quaternion.Inverse(GyroToUnity(Input.gyro.attitude));
XRSettings.LoadDeviceByName("");
yield return null;
XRSettings.enabled = false;
}
private static Quaternion GyroToUnity(Quaternion q)
{
return new Quaternion(q.x, q.y, -q.z, -q.w);
}
// Use this for initialization
void Start () {
if(XRSettings.enabled == false){
Input.gyro.enabled = true;
}
}
void Update()
{
if (XRSettings.enabled)
{
return;
}
//Add the gyro value with the offset then apply to the camera
transform.rotation = offset * GyroToUnity(Input.gyro.attitude);
}
public void StartVR(){
if(XRSettings.enabled == false){
StartCoroutine (SwitchToVR ());
}
}
public void StartN(){
if(XRSettings.enabled == true){
StartCoroutine(SwitchTo2D());
}
}
}
Upvotes: 0
Views: 250
Reputation: 125275
Below is a simple camera follow script that follows a player ball while maintaining the offset distance between the camera and the player. It uses an offset value to do that by subtracting the camera's position from the player's position and then re-applying that offset to the camera's position with current player position in the Update
or LateUpdate
function.
public Transform playerTransform;
public Transform mainCameraTransform = null;
private Vector3 cameraOffset = Vector3.zero;
void Start()
{
mainCameraTransform = Camera.main.transform;
//Get camera-player Transform Offset that will be used to move the camera
cameraOffset = mainCameraTransform.position - playerTransform.position;
}
void LateUpdate()
{
//Move the camera to the position of the playerTransform with the offset that was saved in the beginning
mainCameraTransform.position = playerTransform.position + cameraOffset;
}
The example and code above is not exactly your solution but it's the easiest way to understand what you need to do.
In your case you need to subtract the camera's rotation from the gyro sensor or Input.gyro.attitude
. The minor changes is that you can't really use -
or +
for that since both are Quaternion
not Vector3
as in the example above.
To subtract a Quaternion
from another Quaternion
like I did in the
Start
function with Vector3
, multiply the inverse of the other
Quaternion
. The inverse is
obtained with Quaternion.Inverse
.
To add two Quaternions
like I did in the LateUpdate
function
above with Vector3
, simply multiply both Quaternion
together.
Here is the relevant changes in your code:
Quaternion offset;
IEnumerator SwitchTo2D()
{
Input.gyro.enabled = true;
//Get offset.. Subtract Camera rotation from Gyro rotation
offset = transform.rotation * Quaternion.Inverse(GyroToUnity(Input.gyro.attitude));
XRSettings.LoadDeviceByName("");
yield return null;
}
// Update is called once per frame
void Update()
{
if (XRSettings.enabled)
{
return;
}
//Add the gyro value with the offset then apply to the camera
transform.rotation = offset * GyroToUnity(Input.gyro.attitude);
}
private static Quaternion GyroToUnity(Quaternion q)
{
return new Quaternion(q.x, q.y, -q.z, -q.w);
}
The GyroToUnity
function is used to convert the gyroscope coordinate into Unity's coordinate before applying it to the camera. The gyroscope sensor is using the right-handed coordinate while Unity's camera and other objects are using the left-handed coordinate. See this for more information.
Upvotes: 1