我决定休假学习Unity3D中Vive的开发。 Google搜索了几个示例,并开始尝试,但由于某种原因,它不起作用。 在开始更详细地了解后,发现Valve最近推出了Unity3D的插件更新-一个新的,重做的版本。 它出现了几个基本的创新,使旧教程不再适用。 我决定写一个新的

我们将需要Unity> = 5.4.0和新的SteamVR插件插件 ( GitHub )
在插件本身中,有三个有用的pdf文件可供您熟悉
\资产\ SteamVR \ SteamVR Unity插件.pdf
\ Assets \ SteamVR \ SteamVR Unity插件-输入系统.pdf
\资产\ SteamVR \ InteractionSystem \ InteractionSystem.pdf
还有两个例子:
\资产\ SteamVR \简单Sample.unity
\资产\ SteamVR \ InteractionSystem \样本\ Interactions_Example.unity
该插件支持模拟模式-如果未打开头盔,它将打开
好吧,现在一步一步来;
使用SteamVR插件创建一个新的3D模板项目
我们同意设置

现在的关键是您需要配置管理。 选择菜单项Window \ SteamVR Imput

Unity将询问缺少的actions.json并提供复制示例文件(位于\ Assets \ SteamVR \ Input \ ExampleJSON中)-我建议您同意。

json文件显示,该插件不仅为Vive设计,还为Oculus和Windows MR以及新的关节控制器设计。 与此相关的重大更改。
在打开的窗口中,只需点击“保存并生成”

现在,您需要将播放器(来自\ Assets \ SteamVR \ InteractionSystem \ Core \ Prefabs的播放器)添加到场景中并删除主摄像机

为了使模拟模式起作用-必须在播放器的属性中将其启用

将\ Assets \ SteamVR \ InteractionSystem \ Core \ Icons文件夹复制到\ Assets并将其重命名为Gizmos也很有用
您可以单击播放-但是模拟中只有假手无法使用,您需要从此处复制脚本并将其挂在Player-> NoSteamVRFallbackObjects-> FallbackHand上
假手稿代码using System.Collections.Generic; using UnityEngine; using Valve.VR; public class VrSimulatorHandFixer156 : SteamVR_Behaviour_Pose { Valve.VR.InteractionSystem.Hand _hand; protected override void Start() { base.Start(); _hand = this.gameObject.GetComponent<Valve.VR.InteractionSystem.Hand>(); _hand.handType = SteamVR_Input_Sources.RightHand; GameObject broHand = GameObject.Instantiate(_hand.gameObject); Destroy(broHand.GetComponent<VrSimulatorHandFixer156>()); broHand.SetActive(false); _hand.otherHand = broHand.GetComponent<Valve.VR.InteractionSystem.Hand>(); _hand.otherHand.handType = SteamVR_Input_Sources.LeftHand; var spoofMouse = new SpoofMouseAction(); _hand.grabGripAction = spoofMouse; spoofMouse.InitializeDictionariesExposed(_hand.handType); this.poseAction = new Poser_SteamVR_Action_Pose(); } protected override void OnEnable() { } protected override void Update() { _hand.grabGripAction.UpdateValue(SteamVR_Input_Sources.RightHand); } protected override void OnDisable() { } protected override void CheckDeviceIndex() { }
在VR模式下,控制器已打开-它们将可见

我们添加了VR,但我们甚至无法四处走动。 该插件具有远距传输的实现
要启用它,您需要从\ Assets \ SteamVR \ InteractionSystem \ Teleport \ Prefabs添加到Teleporting场景
并从那里安排TeleportPoint

您也可以使用T键模仿传送。
您可以创建一个隐形运输表面-创建一个平面,并将TeleportArea.cs脚本从\ Assets \ SteamVR \ InteractionSystem \ Teleport \ Script挂在其上

让我们尝试与对象进行交互-创建一个多维数据集,并将Interactable.cs脚本从\ Assets \ SteamVR \ InteractionSystem \ Core \ Script上挂起
现在突出显示了,但没有任何反应

我们需要注册交互-我们将为Cube创建一个新脚本
交互代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using Valve.VR.InteractionSystem; public class NewBehaviourScript : MonoBehaviour { private Hand.AttachmentFlags attachmentFlags = Hand.defaultAttachmentFlags & (~Hand.AttachmentFlags.SnapOnAttach) & (~Hand.AttachmentFlags.DetachOthers) & (~Hand.AttachmentFlags.VelocityMovement); private Interactable interactable; // Use this for initialization void Start () { interactable = this.GetComponent<Interactable>(); } private void HandHoverUpdate(Hand hand) { GrabTypes startingGrabType = hand.GetGrabStarting(); bool isGrabEnding = hand.IsGrabEnding(this.gameObject); if (startingGrabType != GrabTypes.None) { // Call this to continue receiving HandHoverUpdate messages, // and prevent the hand from hovering over anything else hand.HoverLock(interactable); // Attach this object to the hand hand.AttachObject(gameObject, startingGrabType, attachmentFlags); } else if (isGrabEnding) { // Detach this object from the hand hand.DetachObject(gameObject); // Call this to undo HoverLock hand.HoverUnlock(interactable); } } }
可以在插件的示例中找到有关交互的更多详细信息,尤其是在\ Assets \ SteamVR \ InteractionSystem \ Samples \ Scripts \ InteractableExample.cs中
然后,我们将尝试执行示例中未包含的内容-添加新操作
打开Player.cs脚本并添加字段
[SteamVR_DefaultAction("PlayerMove", "default")] public SteamVR_Action_Vector2 a_move; [SteamVR_DefaultAction("PlayerRotate", "default")] public SteamVR_Action_Vector2 a_rotate; [SteamVR_DefaultAction("MenuClick", "default")] public SteamVR_Action_Boolean a_menu;
有效的返回类型可以在\资产\ SteamVR \输入中找到
和Update方法:
private void Update() { bool st = a_menu.GetStateDown(SteamVR_Input_Sources.Any); if (st) { this.transform.position = new Vector3(0, 0, 0); } else { Camera camera = this.GetComponentInChildren<Camera>(); Quaternion cr = Quaternion.Euler(0, 0, 0); if (camera != null) { Vector2 r = a_rotate.GetAxis(SteamVR_Input_Sources.RightHand); Quaternion qp = this.transform.rotation; qp.eulerAngles += new Vector3(0, rx, 0); this.transform.rotation = qp; cr = camera.transform.rotation; } Vector2 m = a_move.GetAxis(SteamVR_Input_Sources.LeftHand); m = Quaternion.Euler(0, 0, -cr.eulerAngles.y) * m; this.transform.position += new Vector3(mx / 10, 0, my / 10); } }
完整的Player.cs代码 //======= Copyright (c) Valve Corporation, All rights reserved. =============== // // Purpose: Player interface used to query HMD transforms and VR hands // //============================================================================= using UnityEngine; using System.Collections; using System.Collections.Generic; namespace Valve.VR.InteractionSystem { //------------------------------------------------------------------------- // Singleton representing the local VR player/user, with methods for getting // the player's hands, head, tracking origin, and guesses for various properties. //------------------------------------------------------------------------- public class Player : MonoBehaviour { [Tooltip( "Virtual transform corresponding to the meatspace tracking origin. Devices are tracked relative to this." )] public Transform trackingOriginTransform; [Tooltip( "List of possible transforms for the head/HMD, including the no-SteamVR fallback camera." )] public Transform[] hmdTransforms; [Tooltip( "List of possible Hands, including no-SteamVR fallback Hands." )] public Hand[] hands; [Tooltip( "Reference to the physics collider that follows the player's HMD position." )] public Collider headCollider; [Tooltip( "These objects are enabled when SteamVR is available" )] public GameObject rigSteamVR; [Tooltip( "These objects are enabled when SteamVR is not available, or when the user toggles out of VR" )] public GameObject rig2DFallback; [Tooltip( "The audio listener for this player" )] public Transform audioListener; public bool allowToggleTo2D = true; [SteamVR_DefaultAction("PlayerMove", "default")] public SteamVR_Action_Vector2 a_move; [SteamVR_DefaultAction("PlayerRotate", "default")] public SteamVR_Action_Vector2 a_rotate; [SteamVR_DefaultAction("MenuClick", "default")] public SteamVR_Action_Boolean a_menu; //------------------------------------------------- // Singleton instance of the Player. Only one can exist at a time. //------------------------------------------------- private static Player _instance; public static Player instance { get { if ( _instance == null ) { _instance = FindObjectOfType<Player>(); } return _instance; } } //------------------------------------------------- // Get the number of active Hands. //------------------------------------------------- public int handCount { get { int count = 0; for ( int i = 0; i < hands.Length; i++ ) { if ( hands[i].gameObject.activeInHierarchy ) { count++; } } return count; } } //------------------------------------------------- // Get the i-th active Hand. // // i - Zero-based index of the active Hand to get //------------------------------------------------- public Hand GetHand( int i ) { for ( int j = 0; j < hands.Length; j++ ) { if ( !hands[j].gameObject.activeInHierarchy ) { continue; } if ( i > 0 ) { i--; continue; } return hands[j]; } return null; } //------------------------------------------------- public Hand leftHand { get { for ( int j = 0; j < hands.Length; j++ ) { if ( !hands[j].gameObject.activeInHierarchy ) { continue; } if ( hands[j].handType != SteamVR_Input_Sources.LeftHand) { continue; } return hands[j]; } return null; } } //------------------------------------------------- public Hand rightHand { get { for ( int j = 0; j < hands.Length; j++ ) { if ( !hands[j].gameObject.activeInHierarchy ) { continue; } if ( hands[j].handType != SteamVR_Input_Sources.RightHand) { continue; } return hands[j]; } return null; } } //------------------------------------------------- // Get Player scale. Assumes it is scaled equally on all axes. //------------------------------------------------- public float scale { get { return transform.lossyScale.x; } } //------------------------------------------------- // Get the HMD transform. This might return the fallback camera transform if SteamVR is unavailable or disabled. //------------------------------------------------- public Transform hmdTransform { get { if (hmdTransforms != null) { for (int i = 0; i < hmdTransforms.Length; i++) { if (hmdTransforms[i].gameObject.activeInHierarchy) return hmdTransforms[i]; } } return null; } } //------------------------------------------------- // Height of the eyes above the ground - useful for estimating player height. //------------------------------------------------- public float eyeHeight { get { Transform hmd = hmdTransform; if ( hmd ) { Vector3 eyeOffset = Vector3.Project( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up ); return eyeOffset.magnitude / trackingOriginTransform.lossyScale.x; } return 0.0f; } } //------------------------------------------------- // Guess for the world-space position of the player's feet, directly beneath the HMD. //------------------------------------------------- public Vector3 feetPositionGuess { get { Transform hmd = hmdTransform; if ( hmd ) { return trackingOriginTransform.position + Vector3.ProjectOnPlane( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up ); } return trackingOriginTransform.position; } } //------------------------------------------------- // Guess for the world-space direction of the player's hips/torso. This is effectively just the gaze direction projected onto the floor plane. //------------------------------------------------- public Vector3 bodyDirectionGuess { get { Transform hmd = hmdTransform; if ( hmd ) { Vector3 direction = Vector3.ProjectOnPlane( hmd.forward, trackingOriginTransform.up ); if ( Vector3.Dot( hmd.up, trackingOriginTransform.up ) < 0.0f ) { // The HMD is upside-down. Either // -The player is bending over backwards // -The player is bent over looking through their legs direction = -direction; } return direction; } return trackingOriginTransform.forward; } } //------------------------------------------------- void Awake() { SteamVR.Initialize(true); //force openvr if ( trackingOriginTransform == null ) { trackingOriginTransform = this.transform; } } //------------------------------------------------- private IEnumerator Start() { _instance = this; while (SteamVR_Behaviour.instance.forcingInitialization) yield return null; if ( SteamVR.instance != null ) { ActivateRig( rigSteamVR ); } else {
运行Window \ SteamVR Imput,在默认集中创建我们的操作并保存,现在选择“打开绑定UI”(SteamVR必须正在运行并且至少一个控制器已打开)

控制器绑定选项卡在浏览器中打开-您需要在其中配置我们的动作与控制器的连接:我们将PlayerMove挂在左侧的TRACKPAD上(不要忘记关闭镜像模式),将PlayerRotate挂在右侧的TRACKPAD上,并挂起MenuClick在菜单键上

关闭控制器绑定并保存更改。
在播放器的属性中,我们将新动作关联

启动播放
专案
结论
应注意几点。 SteamVR Imput中的某些动作会使Unity长时间思考,原则上,您可以在代码中自行进行这些更改,而不是使用Controller Binding,您可以直接编辑json文件,但是存在很大的错误风险,可能很难发现错误。
为了更深入地研究插件-详细研究示例非常有用,当然-阅读文档。