Unity:将 Google Cardboard VR 应用程序部署为 standalone/web 时无法移动?
Unity: can't move when deploying Google Cardboard VR app as standalone/web?
我已经使用 Google Cardboard SDK 在 Unity 中创建了一个 VR 应用程序,现在正尝试将其部署到 Web 并作为一个独立的应用程序。该游戏在 iPhone 和 Android 上运行良好,用户通过转动头部和触摸屏幕来导航游戏(我相信 "Fire1" 命令)。当我切换平台时,问题就来了。
测试时在编辑器中,即使我的电脑没有绑在我的头上,我仍然可以通过按住 Alt 键转动并点击屏幕移动来玩游戏。我认为这在部署到独立系统时是一样的,但我遇到了问题:
当部署到网络和单机版时,用户根本无法移动,因此我什至不确定游戏是否正常运行 - 按住 alt 键没有任何作用,点击屏幕也没有任何作用。他们不能玩游戏。
这里有什么问题?是否有其他我可以专门为独立实现的输入来替换头部跟踪等?其他 Google Cardboard VR 应用程序如何部署到网络?
在我的 WebplayerDevice 脚本中:
//For web support
#if UNITY_WEBPLAYER
using UnityEngine;
using System.Runtime.InteropServices;
using System.Collections.Generic;
public class CardboardWebplayerDevice : BaseCardboardDevice {
// Simulated neck model. Vector from the neck pivot point to the point between the eyes.
private static readonly Vector3 neckOffset = new Vector3(0, 0.075f, 0.08f);
// Use mouse to emulate head in the editor.
private float mouseX = 0;
private float mouseY = 0;
private float mouseZ = 0;
public override void Init() {
Input.gyro.enabled = true;
Debug.Log ("ITS WEB!!");
}
public override bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
return false; // No need for diagnostic message.
}
public override bool SupportsNativeUILayer(List<string> diagnostics) {
return false; // No need for diagnostic message.
}
// Since we can check all these settings by asking Cardboard.SDK, no need
// to keep a separate copy here.
public override void SetUILayerEnabled(bool enabled) {}
public override void SetVRModeEnabled(bool enabled) {}
public override void SetDistortionCorrectionEnabled(bool enabled) {}
public override void SetStereoScreen(RenderTexture stereoScreen) {}
public override void SetSettingsButtonEnabled(bool enabled) {}
public override void SetAlignmentMarkerEnabled(bool enabled) {}
public override void SetVRBackButtonEnabled(bool enabled) {}
public override void SetShowVrBackButtonOnlyInVR(bool only) {}
public override void SetNeckModelScale(float scale) {}
public override void SetAutoDriftCorrectionEnabled(bool enabled) {}
public override void SetElectronicDisplayStabilizationEnabled(bool enabled) {}
public override void SetTapIsTrigger(bool enabled) {}
private Quaternion initialRotation = Quaternion.identity;
private bool remoteCommunicating = false;
private bool RemoteCommunicating {
get {
if (!remoteCommunicating) {
remoteCommunicating = Vector3.Dot(Input.gyro.rotationRate, Input.gyro.rotationRate) > 0.05;
}
return remoteCommunicating;
}
}
public override void UpdateState() {
Quaternion rot;
if (Cardboard.SDK.UseUnityRemoteInput && RemoteCommunicating) {
var att = Input.gyro.attitude * initialRotation;
att = new Quaternion(att.x, att.y, -att.z, -att.w);
rot = Quaternion.Euler(90, 0, 0) * att;
} else {
bool rolled = false;
if (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) {
mouseX += Input.GetAxis("Mouse X") * 5;
if (mouseX <= -180) {
mouseX += 360;
} else if (mouseX > 180) {
mouseX -= 360;
}
mouseY -= Input.GetAxis("Mouse Y") * 2.4f;
mouseY = Mathf.Clamp(mouseY, -85, 85);
} else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) {
rolled = true;
mouseZ += Input.GetAxis("Mouse X") * 5;
mouseZ = Mathf.Clamp(mouseZ, -85, 85);
}
if (!rolled && Cardboard.SDK.autoUntiltHead) {
// People don't usually leave their heads tilted to one side for long.
mouseZ = Mathf.Lerp(mouseZ, 0, Time.deltaTime / (Time.deltaTime + 0.1f));
}
rot = Quaternion.Euler(mouseY, mouseX, mouseZ);
}
var neck = (rot * neckOffset - neckOffset.y * Vector3.up) * Cardboard.SDK.NeckModelScale;
headPose.Set(neck, rot);
triggered = Input.GetMouseButtonDown(0);
tilted = Input.GetKeyUp(KeyCode.Escape);
}
public override void PostRender() {
// Do nothing.
}
public override void UpdateScreenData() {
Profile = CardboardProfile.GetKnownProfile(Cardboard.SDK.ScreenSize, Cardboard.SDK.DeviceType);
ComputeEyesFromProfile();
profileChanged = true;
}
public override void Recenter() {
mouseX = mouseZ = 0; // Do not reset pitch, which is how it works on the phone.
if (RemoteCommunicating) {
//initialRotation = Quaternion.Inverse(Input.gyro.attitude);
}
}
}
#endif
错误(即使我将 Webplayer 设备 class 更改为 BaseVRDevice 也没有任何区别):
按键组合仅在 Unity3d 编辑器中可用。
Cardboard Unity3d SDK通过加载VRDevices下的相关设备脚本,支持不同平台的不同行为:
https://github.com/googlesamples/cardboard-unity/blob/master/Cardboard/Scripts/VRDevices
您将看到 UnityEditorDevice.cs 具有处理 ALT 和 CTRL 键的代码。
对于网络部署,我建议您创建一个新设备并实现鼠标移动(无需按键)以环顾四周。您可以通过编辑 BaseVRDevice.cs:
让 Cardboard SDK 加载您的设备
public static BaseVRDevice GetDevice() {
if (device == null) {
#if UNITY_EDITOR
device = new UnityEditorDevice();
#elif ANDROID_DEVICE
device = new CardboardAndroidDevice();
#elif IPHONE_DEVICE
device = new CardboardiOSDevice();
// Support your device here:
#elif UNITY_WEBPLAYER
device = new CardboardWebplayerDevice();
#else
throw new InvalidOperationException("Unsupported device.");
#endif
}
return device;
}
您看到的编译错误是因为您在 Cardboard.cs 脚本中引用的变量(autoUntiltHead、Screen、Device 等)都在 #if UNITY_EDITOR 部分中。将其更改为 #if UNITY_EDITOR || UNITY_WEBPLAYER,或者只是删除#if。然后就可以编译了。
我已经使用 Google Cardboard SDK 在 Unity 中创建了一个 VR 应用程序,现在正尝试将其部署到 Web 并作为一个独立的应用程序。该游戏在 iPhone 和 Android 上运行良好,用户通过转动头部和触摸屏幕来导航游戏(我相信 "Fire1" 命令)。当我切换平台时,问题就来了。
测试时在编辑器中,即使我的电脑没有绑在我的头上,我仍然可以通过按住 Alt 键转动并点击屏幕移动来玩游戏。我认为这在部署到独立系统时是一样的,但我遇到了问题:
当部署到网络和单机版时,用户根本无法移动,因此我什至不确定游戏是否正常运行 - 按住 alt 键没有任何作用,点击屏幕也没有任何作用。他们不能玩游戏。
这里有什么问题?是否有其他我可以专门为独立实现的输入来替换头部跟踪等?其他 Google Cardboard VR 应用程序如何部署到网络?
在我的 WebplayerDevice 脚本中:
//For web support
#if UNITY_WEBPLAYER
using UnityEngine;
using System.Runtime.InteropServices;
using System.Collections.Generic;
public class CardboardWebplayerDevice : BaseCardboardDevice {
// Simulated neck model. Vector from the neck pivot point to the point between the eyes.
private static readonly Vector3 neckOffset = new Vector3(0, 0.075f, 0.08f);
// Use mouse to emulate head in the editor.
private float mouseX = 0;
private float mouseY = 0;
private float mouseZ = 0;
public override void Init() {
Input.gyro.enabled = true;
Debug.Log ("ITS WEB!!");
}
public override bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
return false; // No need for diagnostic message.
}
public override bool SupportsNativeUILayer(List<string> diagnostics) {
return false; // No need for diagnostic message.
}
// Since we can check all these settings by asking Cardboard.SDK, no need
// to keep a separate copy here.
public override void SetUILayerEnabled(bool enabled) {}
public override void SetVRModeEnabled(bool enabled) {}
public override void SetDistortionCorrectionEnabled(bool enabled) {}
public override void SetStereoScreen(RenderTexture stereoScreen) {}
public override void SetSettingsButtonEnabled(bool enabled) {}
public override void SetAlignmentMarkerEnabled(bool enabled) {}
public override void SetVRBackButtonEnabled(bool enabled) {}
public override void SetShowVrBackButtonOnlyInVR(bool only) {}
public override void SetNeckModelScale(float scale) {}
public override void SetAutoDriftCorrectionEnabled(bool enabled) {}
public override void SetElectronicDisplayStabilizationEnabled(bool enabled) {}
public override void SetTapIsTrigger(bool enabled) {}
private Quaternion initialRotation = Quaternion.identity;
private bool remoteCommunicating = false;
private bool RemoteCommunicating {
get {
if (!remoteCommunicating) {
remoteCommunicating = Vector3.Dot(Input.gyro.rotationRate, Input.gyro.rotationRate) > 0.05;
}
return remoteCommunicating;
}
}
public override void UpdateState() {
Quaternion rot;
if (Cardboard.SDK.UseUnityRemoteInput && RemoteCommunicating) {
var att = Input.gyro.attitude * initialRotation;
att = new Quaternion(att.x, att.y, -att.z, -att.w);
rot = Quaternion.Euler(90, 0, 0) * att;
} else {
bool rolled = false;
if (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) {
mouseX += Input.GetAxis("Mouse X") * 5;
if (mouseX <= -180) {
mouseX += 360;
} else if (mouseX > 180) {
mouseX -= 360;
}
mouseY -= Input.GetAxis("Mouse Y") * 2.4f;
mouseY = Mathf.Clamp(mouseY, -85, 85);
} else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) {
rolled = true;
mouseZ += Input.GetAxis("Mouse X") * 5;
mouseZ = Mathf.Clamp(mouseZ, -85, 85);
}
if (!rolled && Cardboard.SDK.autoUntiltHead) {
// People don't usually leave their heads tilted to one side for long.
mouseZ = Mathf.Lerp(mouseZ, 0, Time.deltaTime / (Time.deltaTime + 0.1f));
}
rot = Quaternion.Euler(mouseY, mouseX, mouseZ);
}
var neck = (rot * neckOffset - neckOffset.y * Vector3.up) * Cardboard.SDK.NeckModelScale;
headPose.Set(neck, rot);
triggered = Input.GetMouseButtonDown(0);
tilted = Input.GetKeyUp(KeyCode.Escape);
}
public override void PostRender() {
// Do nothing.
}
public override void UpdateScreenData() {
Profile = CardboardProfile.GetKnownProfile(Cardboard.SDK.ScreenSize, Cardboard.SDK.DeviceType);
ComputeEyesFromProfile();
profileChanged = true;
}
public override void Recenter() {
mouseX = mouseZ = 0; // Do not reset pitch, which is how it works on the phone.
if (RemoteCommunicating) {
//initialRotation = Quaternion.Inverse(Input.gyro.attitude);
}
}
}
#endif
错误(即使我将 Webplayer 设备 class 更改为 BaseVRDevice 也没有任何区别):
按键组合仅在 Unity3d 编辑器中可用。
Cardboard Unity3d SDK通过加载VRDevices下的相关设备脚本,支持不同平台的不同行为:
https://github.com/googlesamples/cardboard-unity/blob/master/Cardboard/Scripts/VRDevices
您将看到 UnityEditorDevice.cs 具有处理 ALT 和 CTRL 键的代码。
对于网络部署,我建议您创建一个新设备并实现鼠标移动(无需按键)以环顾四周。您可以通过编辑 BaseVRDevice.cs:
让 Cardboard SDK 加载您的设备 public static BaseVRDevice GetDevice() {
if (device == null) {
#if UNITY_EDITOR
device = new UnityEditorDevice();
#elif ANDROID_DEVICE
device = new CardboardAndroidDevice();
#elif IPHONE_DEVICE
device = new CardboardiOSDevice();
// Support your device here:
#elif UNITY_WEBPLAYER
device = new CardboardWebplayerDevice();
#else
throw new InvalidOperationException("Unsupported device.");
#endif
}
return device;
}
您看到的编译错误是因为您在 Cardboard.cs 脚本中引用的变量(autoUntiltHead、Screen、Device 等)都在 #if UNITY_EDITOR 部分中。将其更改为 #if UNITY_EDITOR || UNITY_WEBPLAYER,或者只是删除#if。然后就可以编译了。