当前位置:   article > 正文

VR Interaction Framework2.0插件的使用(适用于Pico串流)

vr interaction framework

        随着Pico被字节收购,追踪优化变好了,Pico的串流也越来越好用了,现在已经可以用于开发了,现在所用的设备为Pico Neo3消费版,个人感觉的使用感受是,比起上万的HTC Vive设备,几千的Pico Neo3消费版,某种程度来说是更加好用的,现在我要介绍的VR开发框架为VRIF,全称为VR Interaction Framework。

VRIF插件获取:Unity商店

VRIF官网:VRIF Wiki

为什么去学习这个框架呢?

1、它适合用多个平台,基本上来说,一次开发就可以打包到大部分的主流的平台,如:PC VR设备、Pico设备、Oculus设备等。

2、得益于Openxr和XR Interaction Toolkit的一致性,而VRIF又集成了XR Interaction Toolkit输入输出,所以它可以做到串流调式和Pico打包无缝衔接。

3、开发速度快,VRIF已经在案例中实现了很多VR开发的常用功能,只要拿来用就行。

4、作者更新快,目前已更新到了2.0,集成了 FinalIK和PhotonPUN 示例。

5、Unity主推,经测试此框架,适配了Pico Neo3/Pico Neo4系例设备

串流调式和Pico打包无缝衔接的实现基于OpenXR+XR Interaction Toolkit这方案,现在Pico最新版SDK就是此进行开发的,而Openxr和XR Interaction Toolkit这方案也适用于HTC vive和Oculus的串流。

VRIF框架的配置

可以理解为大框架,先导入大框架,然后根据要用到的设备导入相应的Sdk,这样就可以多种设备一次切换,打出多个包。

第一步:创建一个新项目,导入Unity新版本输入系统包

 安装完要重启,Untiy改变输入类型都是要重启的,选Yes.

第二步:导入VRIF2.0包

双击VRIF2.0包导入:

 这样VRIF就导入完成了。

第三步:导入OpenXR和XR Interaction Toolkit插件

打开PackageManager,点击+号,选择Add package by name。然后输入:com.unity.xr.interaction.toolkit

导入XR Interaction Toolkit插件,并更新

 

导入Text Mesh Pro插件

 

 导入默认的动作绑定资产

第四步:完成VRIF串流配置

 修改这两项,第二个一定要选Oculus Touch Controller Profile,在Pico串流的情况手柄才能追踪,选了HTC ViveController Profile会手柄追踪不了的。

设置VRIF的输入输出,也可什么也不勾,一样能正常使用,UI射线也不会有问题。

 

 

好了,现在运行这个XR Demo,用Pico串流就可以走SteamVR平台来流玩这个场景了

勾选了XR Interaction Toolkit,会导致UI射线有问题,则:

 取消勾选后,VRIF的射线就没问题了

第五步:导入PicoSDK,完成项目配置

 去官网下载最新的SDK

 解压并将此包放到项目的Assets同级目录下,防止此包某天被删除,再打开就报错了。

 打开PackageManager,点击+号,选择Add package by disl.....。然后找到此包并导入,导入后Apply一下 

勾选Pico

 

最后,打包 

现在打包出来Pico就可以使用了

打包的不同平台

之前已经打包了Pico平台了,现在打包Oculus设备

安装Oculus XR Plugin插件

 取消勾选Pico,勾选OCulus直接打包就可以了

 打包SteamVR,切换成window平台,要在BNG Framework/Integrations/SteamVR/SteamVR路径里面,导入一个包用于StamVR输入,试一下打包,不行再导入SteamVr2.0整个包,请参考:VR Interaction Framework插件的使用_vrif-CSDN博客文章浏览阅读2.8k次,点赞3次,收藏22次。随着VR技术越来越成熟,Untiy版本的不断更新,steamVR和VRTK等旧版本插件不再完美适配最新版本的Unity编辑器,编辑器和插件经常各种报错,推荐使用VRIF进行VR开发,该框架使可以轻松创建自己的交互对象并快速提高工作效率,最大的优势是可以支持所有与 Unity 兼容的 VR眼镜并且和各种新版本Unity编辑器兼容性好。本文主要记录VRIF的环境搭建,基于SteamVR的HTC设备一、软件和插件的获取软件建议使用一个长期支持(LTS)版本的Unity,比较稳定,并且有广泛的支持。对于大多_vrifhttps://blog.csdn.net/weixin_44733991/article/details/125034189?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170391688816800182774826%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170391688816800182774826&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-125034189-null-null.142^v99^pc_search_result_base6&utm_term=vrif&spm=1018.2226.3001.4187

VRIF的UI的Bug问题 

当按下按钮后,不抬起来,Button的颜色变不回来 

修改VRIF的VRUISystem的源码

 修改为,下面这样的:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.EventSystems;
  5. using UnityEngine.InputSystem;
  6. using UnityEngine.UI;
  7. namespace BNG
  8. {
  9. public class VRUISystem : BaseInputModule
  10. {
  11. [Header("XR Controller Options : ")]
  12. [Tooltip("This setting determines if LeftPointerTransform or RightPointerTransform will be used as a forward vector for World Space UI events")]
  13. public ControllerHand SelectedHand = ControllerHand.Right;
  14. #if XRIT_INTEGRATION
  15. [Header("XR Interaction Toolkit Options : ")]
  16. public bool UseXRInteractionToolkitUISystem = true;
  17. #endif
  18. [Tooltip("A transform on the left controller to use when raycasting for world space UI events")]
  19. public Transform LeftPointerTransform;
  20. [Tooltip("A transform on the right controller to use when raycasting for world space UI events")]
  21. public Transform RightPointerTransform;
  22. [Tooltip("Controller Binding to use for input down, up, etc.")]
  23. public List<ControllerBinding> ControllerInput = new List<ControllerBinding>() { ControllerBinding.RightTrigger };
  24. [Tooltip("Unity Input Action used to simulate a click or touch event")]
  25. public InputActionReference UIInputAction;
  26. [Tooltip("If true a PhysicsRaycaster component will be added to the UI camera, allowing physical objects to use IPointer events such as OnPointClick, OnPointEnter, etc.")]
  27. public bool AddPhysicsRaycaster = false;
  28. public LayerMask PhysicsRaycasterEventMask;
  29. [Tooltip("If true the Right Thumbstick will send scroll events to the UI")]
  30. public bool RightThumbstickScroll = true;
  31. [Header("Shown for Debug : ")]
  32. public GameObject PressingObject;
  33. public GameObject DraggingObject;
  34. public GameObject ReleasingObject;
  35. public PointerEventData EventData { get; private set; }
  36. Camera cameraCaster;
  37. private GameObject _initialPressObject;
  38. private bool _lastInputDown;
  39. bool inputDown;
  40. private static VRUISystem _instance;
  41. public static VRUISystem Instance
  42. {
  43. get
  44. {
  45. if (_instance == null)
  46. {
  47. _instance = GameObject.FindObjectOfType<VRUISystem>();
  48. if (_instance == null)
  49. {
  50. // Check for existing event system
  51. EventSystem eventSystem = EventSystem.current;
  52. if (eventSystem == null)
  53. {
  54. eventSystem = new GameObject("EventSystem").AddComponent<EventSystem>(); ;
  55. }
  56. _instance = eventSystem.gameObject.AddComponent<VRUISystem>();
  57. }
  58. }
  59. return _instance;
  60. }
  61. }
  62. protected override void Awake()
  63. {
  64. #if XRIT_INTEGRATION
  65. if(!UseXRInteractionToolkitUISystem) {
  66. initEventSystem();
  67. }
  68. #else
  69. initEventSystem();
  70. #endif
  71. }
  72. protected virtual void initEventSystem()
  73. {
  74. UpdateControllerHand(SelectedHand);
  75. AssignCameraToAllCanvases(cameraCaster);
  76. EventData = new PointerEventData(eventSystem);
  77. EventData.position = new Vector2(cameraCaster.pixelWidth / 2, cameraCaster.pixelHeight / 2);
  78. }
  79. protected override void Start()
  80. {
  81. base.Start();
  82. #if XRIT_INTEGRATION
  83. if (UseXRInteractionToolkitUISystem) {
  84. AssignCameraToAllCanvases(Camera.main);
  85. if (this.gameObject.activeSelf) {
  86. // Debug.Log("Diabling VRIF's VRUISystem since XR Interaction Kit UI support is enabled");
  87. this.enabled = false;
  88. }
  89. }
  90. #else
  91. AssignCameraToAllCanvases(cameraCaster);
  92. #endif
  93. }
  94. void init()
  95. {
  96. if (cameraCaster == null)
  97. {
  98. // Create the camera required for the caster.
  99. // We can reduce the fov and disable the camera component for performance
  100. var go = new GameObject("CameraCaster");
  101. cameraCaster = go.AddComponent<Camera>();
  102. cameraCaster.stereoTargetEye = StereoTargetEyeMask.None;
  103. cameraCaster.fieldOfView = 5f;
  104. cameraCaster.nearClipPlane = 0.01f;
  105. cameraCaster.clearFlags = CameraClearFlags.Nothing;
  106. cameraCaster.enabled = false;
  107. // Add PhysicsRaycaster so other objects can subscribe to IPointer events
  108. if (AddPhysicsRaycaster)
  109. {
  110. var pr = go.AddComponent<PhysicsRaycaster>();
  111. pr.eventMask = PhysicsRaycasterEventMask;
  112. }
  113. }
  114. }
  115. public override void Process()
  116. {
  117. #if XRIT_INTEGRATION
  118. // XRIT doesn't process here
  119. if(UseXRInteractionToolkitUISystem == false) {
  120. DoProcess();
  121. }
  122. #else
  123. DoProcess();
  124. #endif
  125. }
  126. public void DoProcess()
  127. {
  128. // Input isn't ready if this Camera Caster's gameObject isn't active
  129. if (EventData == null || !CameraCasterReady())
  130. {
  131. return;
  132. }
  133. EventData.position = new Vector2(cameraCaster.pixelWidth / 2, cameraCaster.pixelHeight / 2);
  134. eventSystem.RaycastAll(EventData, m_RaycastResultCache);
  135. EventData.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
  136. m_RaycastResultCache.Clear();
  137. // Handle Hover
  138. HandlePointerExitAndEnter(EventData, EventData.pointerCurrentRaycast.gameObject);
  139. // Handle Drag
  140. ExecuteEvents.Execute(EventData.pointerDrag, EventData, ExecuteEvents.dragHandler);
  141. // Handle scroll
  142. if (RightThumbstickScroll)
  143. {
  144. EventData.scrollDelta = InputBridge.Instance.RightThumbstickAxis;
  145. if (!Mathf.Approximately(EventData.scrollDelta.sqrMagnitude, 0))
  146. {
  147. ExecuteEvents.Execute(ExecuteEvents.GetEventHandler<IScrollHandler>(EventData.pointerCurrentRaycast.gameObject), EventData, ExecuteEvents.scrollHandler);
  148. }
  149. }
  150. // Press Events
  151. inputDown = InputReady();
  152. // On Trigger Down > TriggerDownValue this frame but not last
  153. if (inputDown && _lastInputDown == false)
  154. {
  155. PressDown();
  156. }
  157. // On Held Down
  158. else if (inputDown)
  159. {
  160. //Press();
  161. }
  162. // On Release
  163. else
  164. {
  165. Release();
  166. }
  167. _lastInputDown = inputDown;
  168. }
  169. public virtual bool InputReady()
  170. {
  171. // Input isn't ready if this Camera Caster's gameObject isn't active
  172. if (!CameraCasterReady())
  173. {
  174. return false;
  175. }
  176. // Check Unity Action
  177. if (UIInputAction != null && UIInputAction.action.ReadValue<float>() == 1f)
  178. {
  179. return true;
  180. }
  181. // Check for bound controller button
  182. for (int x = 0; x < ControllerInput.Count; x++)
  183. {
  184. if (InputBridge.Instance.GetControllerBindingValue(ControllerInput[x]))
  185. {
  186. return true;
  187. }
  188. }
  189. return false;
  190. }
  191. /// <summary>
  192. /// Returns true if we have a camera caster enabled and ready to send out data
  193. /// Returns false if the camera caster is null or it's gameobject is disabled
  194. /// </summary>
  195. /// <returns></returns>
  196. public virtual bool CameraCasterReady()
  197. {
  198. if (cameraCaster != null && !cameraCaster.gameObject.activeInHierarchy)
  199. {
  200. return false;
  201. }
  202. return true;
  203. }
  204. public virtual void PressDown()
  205. {
  206. EventData.pointerPressRaycast = EventData.pointerCurrentRaycast;
  207. // Deselect if selection changed
  208. if (_initialPressObject != null)
  209. {
  210. ExecuteEvents.Execute(_initialPressObject, EventData, ExecuteEvents.deselectHandler);
  211. _initialPressObject = null;
  212. }
  213. _initialPressObject = ExecuteEvents.GetEventHandler<IPointerClickHandler>(EventData.pointerPressRaycast.gameObject);
  214. // Set Press Objects and Events
  215. SetPressingObject(_initialPressObject);
  216. ExecuteEvents.Execute(EventData.pointerPress, EventData, ExecuteEvents.pointerDownHandler);
  217. // Set Drag Objects and Events
  218. SetDraggingObject(ExecuteEvents.GetEventHandler<IDragHandler>(EventData.pointerPressRaycast.gameObject));
  219. ExecuteEvents.Execute(EventData.pointerDrag, EventData, ExecuteEvents.beginDragHandler);
  220. }
  221. public virtual void Press()
  222. {
  223. EventData.pointerPressRaycast = EventData.pointerCurrentRaycast;
  224. // Set Press Objects and Events
  225. SetPressingObject(ExecuteEvents.GetEventHandler<IPointerClickHandler>(EventData.pointerPressRaycast.gameObject));
  226. ExecuteEvents.Execute(EventData.pointerPress, EventData, ExecuteEvents.pointerDownHandler);
  227. // Set Drag Objects and Events
  228. SetDraggingObject(ExecuteEvents.GetEventHandler<IDragHandler>(EventData.pointerPressRaycast.gameObject));
  229. ExecuteEvents.Execute(EventData.pointerDrag, EventData, ExecuteEvents.beginDragHandler);
  230. }
  231. public virtual void Release()
  232. {
  233. SetReleasingObject(ExecuteEvents.GetEventHandler<IPointerClickHandler>(EventData.pointerCurrentRaycast.gameObject));
  234. // Considered a click event if released after an initial click
  235. if (EventData.pointerPress == ReleasingObject)
  236. {
  237. ExecuteEvents.Execute(EventData.pointerPress, EventData, ExecuteEvents.pointerClickHandler);
  238. }
  239. ExecuteEvents.Execute(EventData.pointerPress, EventData, ExecuteEvents.pointerUpHandler);
  240. ExecuteEvents.Execute(EventData.pointerDrag, EventData, ExecuteEvents.endDragHandler);
  241. // Send deselect to
  242. ExecuteEvents.Execute(ReleasingObject, EventData, ExecuteEvents.deselectHandler);
  243. ClearAll();
  244. }
  245. public virtual void ClearAll()
  246. {
  247. SetPressingObject(null);
  248. SetDraggingObject(null);
  249. EventData.pointerCurrentRaycast.Clear();
  250. }
  251. public virtual void SetPressingObject(GameObject pressing)
  252. {
  253. EventData.pointerPress = pressing;
  254. PressingObject = pressing;
  255. }
  256. public virtual void SetDraggingObject(GameObject dragging)
  257. {
  258. EventData.pointerDrag = dragging;
  259. DraggingObject = dragging;
  260. }
  261. public virtual void SetReleasingObject(GameObject releasing)
  262. {
  263. ReleasingObject = releasing;
  264. }
  265. public virtual void AssignCameraToAllCanvases(Camera cam)
  266. {
  267. Canvas[] allCanvas = FindObjectsOfType<Canvas>();
  268. for (int x = 0; x < allCanvas.Length; x++)
  269. {
  270. AddCanvasToCamera(allCanvas[x], cam);
  271. }
  272. }
  273. public virtual void AddCanvas(Canvas canvas)
  274. {
  275. #if XRIT_INTEGRATION
  276. if(UseXRInteractionToolkitUISystem) {
  277. AddCanvasToCamera(canvas, Camera.main);
  278. // Add raycaster if not already present
  279. canvas.gameObject.AddComponent<UnityEngine.XR.Interaction.Toolkit.UI.TrackedDeviceGraphicRaycaster>();
  280. }
  281. else {
  282. AddCanvasToCamera(canvas, cameraCaster);
  283. }
  284. #else
  285. AddCanvasToCamera(canvas, cameraCaster);
  286. #endif
  287. }
  288. public virtual void AddCanvasToCamera(Canvas canvas, Camera cam)
  289. {
  290. if (cam != null)
  291. {
  292. canvas.worldCamera = cam;
  293. }
  294. }
  295. public virtual void UpdateControllerHand(ControllerHand hand)
  296. {
  297. // Make sure variables exist
  298. init();
  299. // Setup the Transform
  300. if (hand == ControllerHand.Left && LeftPointerTransform != null)
  301. {
  302. cameraCaster.transform.parent = LeftPointerTransform;
  303. cameraCaster.transform.localPosition = Vector3.zero;
  304. cameraCaster.transform.localEulerAngles = Vector3.zero;
  305. }
  306. else if (hand == ControllerHand.Right && RightPointerTransform != null)
  307. {
  308. cameraCaster.transform.parent = RightPointerTransform;
  309. cameraCaster.transform.localPosition = Vector3.zero;
  310. cameraCaster.transform.localEulerAngles = Vector3.zero;
  311. }
  312. }
  313. }
  314. }

Button的导航选为None,这个在Andoroid上点用都没有,还会导致UGUI有Bug

这样VRIF的交互与UGUI就行了,射线进入为Highlighted Color,按下为Pressed Color,Selected Color不触发。

 现在Bug就解决了,也实现了一次开发多个平台的分发,也可以串流实时调式了,如果是Pico要应用加密,则在XR Rig Advanced加上PXR Manager脚本就行了。

完结!!!

撒花!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/109249
推荐阅读
相关标签
  

闽ICP备14008679号