VR 开发中遇到的问题、解决方案、技巧等
1. VR 手柄按键绑定
在 Unity 顶部菜单栏选择 Window
-> SteamVR_Input
,打开 SteamVR Input 窗口。
在 Action
标签页中,选择 Create New Action Set
,创建一个新的 Action Set,命名为 Menu
,点击 Save and Generate
保存。
在 SteamVR Input 窗口中,选择 Open Binding UI
,打开 SteamVR Input 窗口,选择当前项目,进入按键绑定界面。
选择要自定义的按键,点击编辑,找到 Menu
,最后 替换默认绑定
即可,
2. 设置游戏中手持手柄
在目录中找到如下预制体:SteamVR
-> Prefabs
-> vr_glove_left_model_slim
,设置绑定脚本中的 Range Of Motion
为 With controller
。
3. SteamVR的按钮交互与抓取
3.1 Button
Interactable脚本:
/SteamVR/InteractionSystem/Core/Scripts/Interactable.cs
HoverButton脚本:
/SteamVR/InteractionSystem/Core/Scripts/HoverButton.cs
此脚本需要一个可进行Hover的对象
<MovingPart>
该脚本有三个函数调用需要进行脚本编写实现:OnButtonUp、OnButtonDown、OnButtonIsPressed
3.1 Throwable
Interactable脚本:
/SteamVR/InteractionSystem/Core/Scripts/Interactable.cs
Throwable脚本:
/SteamVR/InteractionSystem/Core/Scripts/Throwable.cs
InteractableHoverEvents脚本:
/SteamVR/InteractionSystem/Core/Scripts/InteractableHoverEvents.cs
此脚本需要一个可进行Hover的对象
<MovingPart>
该脚本有四个函数调用需要进行脚本编写实现:OnHandHoverBegin、OnAttachedToHand(Handhand)、OnDetachedFromHand(Handhand)
Hand类型来自:using Valve.VR.InteractionSystem;
4. 读取Resources文件夹下的json文件
public class YourType { public string name; public List<string> things; } // 读取json文件,获取json字符串 string jsonStr = Resources.Load<TextAsset>("fileName").text; // 将json字符串转换为对象 YourType jsonObj = JsonUtility.FromJson<YourType>(jsonStr);
5. 打开streamingAssets下的exe程序
string path = Application.streamingAssetsPath + "/sceneTwo/AdministrativeHall.exe"; Application.OpenURL(path);
6. VR场景黑屏过渡
在VR Camera
上添加SteamVR_Fade
脚本组件,调用SteamVR_Fade.Start
方法即可。
using Valve.VR; // 第一个参数为渐变到的颜色,第二个参数为渐变的时间 SteamVR_Fade.Start(Color.clear, 0); // 渐变到透明 SteamVR_Fade.Start(Color.black, 1f); // 渐变到黑色
7. VR手柄提示
// 设置手柄提示 void SetGrabPinchHint(bool isBoth, string text = null) { for (int actionIndex = 0; actionIndex < SteamVR_Input.actionsIn.Length; actionIndex++) { ISteamVR_Action_In action = SteamVR_Input.actionsIn[actionIndex]; if (action.GetShortName() == "GrabPinch") { // 循环Hands,设置手柄提示 foreach (var hand in Hands) { if (action.GetActive(hand.handType)) { hand.TriggerHapticPulse(0); // 判断左右手 if (hand.handType == SteamVR_Input_Sources.LeftHand) { // 左手 ControllerButtonHints.ShowTextHint(hand, action, text ?? "左手按钮"); } else { // 右手 ControllerButtonHints.ShowTextHint(hand, action, text ?? "右手按钮"); } } } break; } } }
8. 编辑器运行时
编辑器运行时运行代码,可以使用ExecuteInEditMode
特性,该特性可以让脚本在编辑器运行时运行。
using UnityEngine; [ExecuteInEditMode] public class Env_FlashPointCtrl : Controller { [Header("点位名称")] public string pointName = "FlashPoint"; // 当pointName变化时,更新点位名称 void OnValidate() { gameObject.name = pointName; } }
9. UI追踪玩家
using UnityEngine; public class VR_FollowCamCtrl : Controller { [Header("追踪空物体"), SerializeField] Transform followMainCam_TF; [Header("追踪速度"), SerializeField] float followSpeed = 3f; [Header("追踪距离"), SerializeField] float distance = 0.8f; void Update() { followMainCam_TF.position = Camera.main.transform.position + Vector3.ProjectOnPlane(Camera.main.transform.forward, Vector3.up).normalized * distance; followMainCam_TF.LookAt(Camera.main.transform); transform.position = Vector3.Lerp(transform.position, followMainCam_TF.position, Time.deltaTime * followSpeed); // 使物体的朝向与相机的朝向相反 transform.rotation = Quaternion.LookRotation(transform.position - Camera.main.transform.position); } }
10. VR手柄按键按下
using UnityEngine; public class VR_ControllerCtrl : Controller { SteamVR_Action_Boolean point; void Start() { point = SteamVR_Input.GetBooleanAction("Point"); } void Update() { if (actionBoolean.GetStateDown(SteamVR_Input_Sources.Any)) { Debug.Log("按下 Point"); } } }
11. 游戏对象Y轴面朝相机
using UnityEngine; public class VR_FaceCameraCtrl : Controller { void Update() { // 获取摄像机的位置 Vector3 cameraPosition = Camera.main.transform.position; // 计算物体需要朝向的方向向量 Vector3 targetDirection = new Vector3(cameraPosition.x - transform.position.x, 0, cameraPosition.z - transform.position.z); // 使用LookRotation函数计算出旋转角度 Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up); // 将物体的旋转角度设置为目标角度 transform.rotation = Quaternion.Euler(0, targetRotation.eulerAngles.y, 0); } }