Unity VR游戏开发干货教程:VR中的交互方式

2023-05-16

游戏程序
平台类型: 虚拟VR 
程序设计:  
编程语言:  
引擎/SDK: Unity3D/2D 

Unity VR游戏开发干货教程:VR中的交互方式 ...


  GameRes游资网授权发布 文 / 王寒

  在VR项目中,我们需要在用户”凝视“某个物体时将其激活。在VRSamples中,我们构建了一个简单的,可拓展的轻度系统,让用户跟场景中的物体进行交互。其中包含了三个主要的脚本文件:VREyeRaycaster,VRInput和VRInteractiveItem,下面将对这三个重要的类进行简要的介绍。相关的源代码也做了注释。

  VREyeRaycaster

Unity VR游戏开发干货教程:VR中的交互方式 ...


  该脚本需要和Main Camera关联。在每次调用Update()时,该脚本都会使用Physics.Raycast来投射一条射线,以确认该射线是否命中任何collider(碰撞体)。使用该脚本还可以排除特定的Unity - Manual: Layers-在某些场景中,我们可能为了性能考虑,把所有的可交互对象移到一个单独的层。

  如果某个碰撞体被射线命中,那么该脚本将尝试在GameObject上找到一个VRInteractiveItem组件。

  C#脚本:

  1. VRInteractiveItem interactible = hit.collider.GetComponent<VRInteractiveItem>(); 
  2. //attempt to get the VRInteractiveItem on the hit object
复制代码

  从这里我们就可以判断用户究竟在”凝视“哪个物体,或是停止”凝视“某个物体。如果用户开始或停止”凝视“某个物体,那么我们就可以进行一些处理,比如调用一个方法。

  VRInput

Unity VR游戏开发干货教程:VR中的交互方式 ...


  VRInput是个简单的类,可以判断用户在GearVR上(或是使用DK2时在PC上)所进行的一些简单操作,比如滑动、触碰、或双触。

  我们可以直接在VRInput上订阅事件:

  C#脚本:

  1. public event Action<SwipeDirection> OnSwipe; 
  2. // Called every frame passing in the swipe, including if there is no swipe.
  3. public event Action OnClick; 
  4. // Called when Fire1 is released and it's not a double click.
  5. public event Action OnDown; 
  6. // Called when Fire1 is pressed.
  7. public event Action OnUp; 
  8. // Called when Fire1 is released.
  9. public event Action OnDoubleClick; 
  10. // Called when a double click is detected.
  11. public event Action OnCancel; 
  12. // Called when Cancel is pressed.
复制代码

  VRInteractiveItem

  我们可以把该组件添加到任何希望在VR场景中进行交互的GameObject上,在该物体上需要绑定一个碰撞体。

  对此我们可以选择订阅六种不同的事件:

  C#脚本:

  1. public event Action OnOver; 
  2. // Called when the gaze moves over this object
  3. public event Action OnOut; 
  4. // Called when the gaze leaves this object
  5. public event Action OnClick; 
  6. // Called when click input is detected whilst the gaze is over this object.
  7. public event Action OnDoubleClick; 
  8. // Called when double click input is detected whilst the gaze is over this object.
  9. public event Action OnUp; 
  10. // Called when Fire1 is released whilst the gaze is over this object.
  11. public event Action OnDown; 
  12. // Called when Fire1 is pressed whilst the gaze is over this object.
复制代码

  此外还有一个布尔值用于判断用户是否”凝视“在当前物体上?

  C#脚本:

  1. public bool IsOver
  2. {
  3. get{ return m_IsOver; } // Is the gaze currently over this object?
  4. }
复制代码

  我们也可以创建自己的脚本对以上事件作出响应。下面是一个简单的示例:

  C#脚本:

  1. using UnityEngine;
  2. using VRStandardAssets.Utils;
  3. namespace VRStandardAssets.Examples
  4. {
  5. // This script is a simple example of how an interactive item can
  6. // be used to change things on gameobjects by handling events.
  7. public class ExampleInteractiveItem : MonoBehaviour
  8. {
  9. [SerializeField] private Material m_NormalMaterial; 
  10. [SerializeField] private Material m_OverMaterial; 
  11. [SerializeField] private Material m_ClickedMaterial; 
  12. [SerializeField] private Material m_DoubleClickedMaterial; 
  13. [SerializeField] private VRInteractiveItem m_InteractiveItem;
  14. [SerializeField] private Renderer m_Renderer;
  15. private void Awake ()
  16. {
  17. m_Renderer.material = m_NormalMaterial;
  18. }
复制代码

  如果想看到实际的示例,不妨看看VRSampleScens/Scens/Examples/的InteractiveItem场景。

  SelectionRadial和SelectionSlider

  我们同时利用了radial选择条(SelectionRadial),以及选择滑动条(SelectionSlider),这样用户就可以按住Fire1来确认某个交互:

Unity VR游戏开发干货教程:VR中的交互方式 ...


Unity VR游戏开发干货教程:VR中的交互方式 ...


  当按住输入键时,选择条会进行填充,并在填充完整后分发OnSelectionComplete或OnBarFilled事件。关于此部分的代码,可以在SelectionRadial.cs和SelectionSlider.cs中找到,并进行了详细的注释。

  在VR的世界里,从用户交互的角度看,用户需要时刻知道自己在做什么,而且可以掌控一切。通过这种“held input”的确认输入方式,可以确保用户不会出现误操作。

  VR Sample项目中的交互示例

  现在让我们来一起看看VR Sample项目中的部分交互示例。我们将提到每个场景中所使用的交互方式,以及具体实现的方式。

  Menu 场景中的交互

  每个menu场景都包含了几个组件,其中我们需要重点关注的是MenuButton,VRInteractiveItem和Mesh Collider。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  MenuButton组件订阅了VRInteractiveItem组件上的OnOver和OnOut事件,这样当十字准星移到menu上时,selection radial会出现。当用户的实现离开菜单选项时,selection radial会消失。而当selection radial可见,且用户按住Fire1键时,则radial会自动填充:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  该类还订阅了OnSelectionRadial的OnSelectionComplete事件,这样当radial被填充满的时候,会调用HandleSelectionComplete。该方法的作用是让摄像机淡出,并调用所选的关卡。
C#脚本:

  1. private void OnEnable ()
  2. {
  3. m_InteractiveItem.OnOver += HandleOver;
  4. m_InteractiveItem.OnOut += HandleOut;
  5. m_SelectionRadial.OnSelectionComplete += HandleSelectionComplete;
  6. }
  7. private void OnDisable ()
  8. {
  9. m_InteractiveItem.OnOver -= HandleOver;
  10. m_InteractiveItem.OnOut -= HandleOut;
  11. m_SelectionRadial.OnSelectionComplete -= HandleSelectionComplete;
  12. }
  13. private void HandleOver()
  14. {
  15. // When the user looks at the rendering of the scene, show the radial.
  16. m_SelectionRadial.Show();
  17. m_GazeOver = true;
  18. }
  19. private void HandleOut()
  20. {
  21. // When the user looks away from the rendering of the scene, hide the radial.
  22. m_SelectionRadial.Hide();
  23. m_GazeOver = false;
  24. }
  25. private void HandleSelectionComplete()
  26. {
  27. // If the user is looking at the rendering of the scene when the radial's selection finishes, activate the button.
  28. if(m_GazeOver)
  29. StartCoroutine (ActivateButton());
  30. }
  31. private IEnumerator ActivateButton()
  32. {
  33. // If the camera is already fading, ignore.
  34. if (m_CameraFade.IsFading)
  35. yield break;
  36. // If anything is subscribed to the OnButtonSelected event, call it.
  37. if (OnButtonSelected != null)
  38. OnButtonSelected(this);
  39. // Wait for the camera to fade out.
  40. yield return StartCoroutine(m_CameraFade.BeginFadeOut(true));
  41. // Load the level.
  42. SceneManager.LoadScene(m_SceneToLoad, LoadSceneMode.Single);
  43. }
复制代码

  让我们来看看Selection Radial的部分示例,注意截图中间的粉色元素:

  Reticle only

Unity VR游戏开发干货教程:VR中的交互方式 ...


  当用户“凝视”菜单选项时,空白的Selection Radial可见。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  Selection Radial 填充(当用户“凝视”菜单选项,且按下fire1输入键)

Unity VR游戏开发干货教程:VR中的交互方式 ...


  在整个示例项目中,我们尝试用同样的风格,也就是使用bar和radial以固定的速度进行填充。在此建议大家在开发自己的VR项目时注意到这一点,因为交互设计中的连贯性对用户很重要,特别是对于VR这种新媒介。

  Maze场景中的交互

  Maze(迷宫)游戏中提供了一个桌面式的交互示例,其中我们可以指引游戏角色到出口,并避免触发炮塔。

  在选择角色的目的地时,会出现一个目的地标记,同时还会显示一个角色的路径。玩家可以通过在触摸板上使用swipe,按下方向键,或是使用游戏操纵杆上的左键来旋转视图。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  在MazeFloor游戏对象上关联了MeshCollider和VRInteractiveItem,从而允许在VR场景中进行交互:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  MazeCourse 游戏对象是一个parent对象,其中包含了MazeFloor和MazeWalls GameObjects,这两个对象依次包含了迷宫布局中的几何信息。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  MazeCourse关联了一个MazeTargetSetting脚本,其中包含了对MazeFloor对象上VRInteractiveItem组件的引用。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  MazeTargetSetting订阅了VRInteractiveItem上的OnDoubleClick事件,随后会分发OnTargetSet事件。该事件将把十字准星的Transform作为参数:

  C#脚本:

  1. public event Action<Transform> OnTargetSet; 
  2. // This is triggered when a destination is set. 
  3. private void OnEnable()
  4. {
  5. m_InteractiveItem.OnDoubleClick += HandleDoubleClick;
  6. }
  7. private void OnDisable()
  8. {
  9. m_InteractiveItem.OnDoubleClick -= HandleDoubleClick;
  10. }
  11. private void HandleDoubleClick()
  12. {
  13. // If target setting is active and there are subscribers to OnTargetSet, call it.
  14. if (m_Active && OnTargetSet != null)
  15. OnTargetSet (m_Reticle.ReticleTransform);
  16. }
复制代码

  MazeCharacter游戏对象上的Player组件和MazeDestinationMarketGUI游戏对象上的DestinationMarker组件都会订阅该事件,并作出相应的响应。

  游戏角色可以使用Nav Mesh systems在迷宫中进行路径判断。Player组件使用HandleSetTarget函数来判断Nav Mesh Agent到十字准星间的方向,并更新Agent的轨迹-游戏角色路径的视觉渲染。

  C#脚本:

  1. private void HandleSetTarget(Transform target)
  2. {
  3. // If the game isn't over set the destination of the AI controlling the character and the trail showing its path.
  4. if (m_IsGameOver)
  5. return; 
  6. m_AiCharacter.SetTarget(target.position);
  7. m_AgentTrail.SetDestination();
  8. }
复制代码

  DestinationMarker可以将标记移动到Reticle的Transform位置:

  C#脚本:

  1. private void HandleTargetSet(Transform target)
  2. {
  3. // When the target is set show the marker.
  4. Show();
  5. // Set the marker's position to the target position.
  6. transform.position = target.position;
  7. // Play the audio.
  8. m_MarkerMoveAudio.Play();
  9. // Play the animation on whichever layer it is on, with no time offset.
  10. m_Animator.Play(m_HashMazeNavMarkerAnimState, -1, 0.0f);
  11. }
复制代码

  在下图中可以看到reticle,目的地标记,玩家和轨迹。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  迷宫中的切换开关也是在VR中和物体进行交互的示例,其中用到了Collider,以及VRInteractiveItem,和SelectionSlider三个类。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  正如上图中显示的,和其它交互对象一起,SelectionSlider脚本会监听由VRInteractiveItem和VRInput所分发的事件。

  C#脚本:

  1. private void OnEnable ()
  2. {
  3. m_VRInput.OnDown += HandleDown;
  4. m_VRInput.OnUp += HandleUp;
  5. m_InteractiveItem.OnOver += HandleOver;
  6. m_InteractiveItem.OnOut += HandleOut;
  7. }
复制代码

  Flyer场景中的交互

  Flyer场景是一个计时”无尽飞行”游戏,在其中玩家可以通过四处看来引导飞船的方向,并使用Fire1输入键进行射击,通过击中陨石或是引导飞船穿越空中的门来得分,跟Pilotwings或Starfox这两款游戏有点类似。

  在交互方面,Flyer使用了更简单的方式,也就是让FlyerLaserController订阅VRInput的OnDown事件,从而发射激光。

  C#脚本:

  1. private void OnEnable()
  2. {
  3. m_VRInput.OnDown += HandleDown;
  4. }
  5. private void HandleDown()
  6. {
  7. // If the game isn't running return.
  8. if (!m_GameController.IsGameRunning)
  9. return;
  10. // Fire laser from each position.
  11. SpawnLaser(m_LaserSpawnPosLeft);
  12. SpawnLaser(m_LaserSpawnPosRight);
  13. }
复制代码

  Shooter180和Shooter360场景中的交互(Target Gallery/ Target Arena)。

  在VR Samples包含了两个射击游戏,其中一个是回廊射击游戏,玩家在180度视角的走廊中对潜在目标射击。另外还有一个竞技场射击游戏,玩家被类似X战警场景的潜在目标包围。

  这两款游戏中的每个目标对象都有一个Collider,VRInteractiveItem和ShootingTarget。

Unity VR游戏开发干货教程:VR中的交互方式 ...


Unity VR游戏开发干货教程:VR中的交互方式 ...


  ShootingTarget组件订阅了VRInteractiveItem的OnDown事件,以判断目标是否被击中。该方法适用于瞬间命中(比如激光枪这种)的设定,如果要展示子弹时间,我们就需要考虑其它解决方案了。

  现在我们应该对基本的VR交互组件有了大概的印象,包括任何在VR Samples项目中具体使用这些组件。现在让我们来看看VR Samples项目中如何使用gaze(凝视)和reticles(十字星)。

  GAZE(凝视)

  在VR应用中判断用户正在看什么很重要,可能是用于判断用户和游戏对象的交互,或是触发一个动画,也可能是向目标发射子弹。我们将VR中“看”这个动作定义为gaze(凝视),而在后续的教程中我们将频繁使用这个词。

  考虑到目前大多数HMD头戴设备还不支持眼部追踪,因此我们只能估计用户的gaze(凝视)。透镜的扭曲意味着用户正看着正前方,有一个简单的解决方案。正如在概览中提到的,我们只需要从摄像机的中心发射一条射线,然后找到这条射线所碰撞的物体即可。当然,这就意味着所有要被碰撞(或是需要通过“凝视”进行交互)的对象都必须关联一个Collider组件。

  Reticle(十字准星)

  十字准星用于辅助标记用户视野的中心。十字准星的样式可能是简单的点,也可能是一个十字准线,具体形式取决于项目需求。

  在传统的3D游戏中,十字准星被设置为空间中的固定点,比如通常是屏幕的中央。但是在VR中使用十字准星变得非常复杂:当用户在VR环境中四处观望时,双眼将汇集在靠近摄像机的物体上。如果十字准星处在一个固定的位置,那么用户会看到两个准星:我们在现实世界里面可以轻易模仿这种效果。把某个手指放在眼睛前面,然后聚焦到近处和远处的物体上。当我们聚焦在这个手指上时,就会看到两个背景,反之亦然。这就是传说中的Diplopia 现象。

  为了避免用户在查看周围环境和注视不同距离的物体时看到两个准星,我们需要将准星放到3D空间的同一个点,也就是用户所关注对象的表面。

  将准星放在空间的这个点意味着从远处看准星将非常小,当靠近时会变大。为了让准星的大小不随距离发生变化,我们需要根据它到摄像机的距离对其进行缩放。

  为了说明这一点,我们从Examples/Reticle场景中找了一些例子,展示了处于不同距离和比例的准星。

  准星放置在靠近摄像机的物体上:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  准星放置在稍远的物体上:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  准星放置在远处:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  根据所处的位置和自身比例,用户在任何距离上看到的准星大小都是相同的。

  如果没有击中任何对象,那么我们只需把准星放到一个预设的距离上。在室外环境中,可能会放在摄像机的Far clip plane前面,在室内场景中可能会近得多。

  将十字准星渲染到其它游戏对象的表面

  如果十字准星恰好和某个对象的位置相同,那么准星可能会嵌入到临近的对象中。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  为了解决这个问题,我们需要确保将准星渲染到场景中所有对象的前面。在VR Samples中,我们提供了一个shader,基于Unity现有的名为UIOverlay.shader的”UI/Unlit/Text” shader。在选择某个材质的shader时,可以在”UI/Overlay”中找到。

  这个shader对UI 元素和文本都适用,会在场景中其它物体的前面绘制。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  将准星和场景中的游戏对象对齐

  我们希望准星的旋转方向和它所命中的对象的法线相匹配。通过RaycastHit.normal就可以实现这一点,以下是具体的实现代码:

  C#脚本:

  1. public void SetPosition (RaycastHit hit)
  2. {
  3. m_ReticleTransform.position = hit.point;
  4. m_ReticleTransform.localScale = m_OriginalScale * hit.distance;
  5. // If the reticle should use the normal of what has been hit...
  6. if (m_UseNormal)
  7. // ... set it's rotation based on it's forward vector facing along the normal.
  8. m_ReticleTransform.rotation = Quaternion.FromToRotation (Vector3.forward, hit.normal);
  9. else
  10. // However if it isn't using the normal then it's local rotation should be as it was originally.
  11. m_ReticleTransform.localRotation = m_OriginalRotation;
  12. }
复制代码

  我们可以在Maze场景中看到这个action。

  下图展示了准星如何匹配墙壁的法线:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  下图展示了准星如何匹配地板的法线:

Unity VR游戏开发干货教程:VR中的交互方式 ...


  我们还提供了一个示例的Reticle脚本。该脚本可以跟VREyeRaycaster一起适用,从而将准星放置到场景的正确位置,并且可以选择跟所命中的对象法线帖齐。

Unity VR游戏开发干货教程:VR中的交互方式 ...


  以上内容都可以在VRSampleScens/Scens/Examples/中看到。

  在VR项目中头部的旋转和位置

  在头戴设备中跟踪头部的旋转和位置可以用沉浸式的体验来感受周围环境,但同时也可以让对象根据这些数值所相应的相应。

  为了获取这些数值我们需要用到VR.InputTracking类,并指定我们要访问的VRNode。为了获取头部的旋转,我们会希望用到VRNode.Head,而不是两只眼睛。想了解更多的信息,可以参考Getting Started with VR Development一文中的Camera Nodes。

  使用头部旋转作为输入方式的可能应用是精细旋转菜单或是其它对象。在VRSampleScenes/Examples/Rotation场景中可以看到这一点的示例。

  下面是ExampleRotation的脚本:

  C#脚本:

  1. // Store the Euler rotation of the gameobject.
  2. var eulerRotation = transform.rotation.eulerAngles;
  3. // Set the rotation to be the same as the user's in the y axis.
  4. eulerRotation.x = 0;
  5. eulerRotation.z = 0;
  6. eulerRotation.y = InputTracking.GetLocalRotation(VRNode.Head).eulerAngles.y;
复制代码

  下面的图展示了游戏对象如何根据用户所注视的位置来进行旋转:

Unity VR游戏开发干货教程:VR中的交互方式 ...


Unity VR游戏开发干货教程:VR中的交互方式 ...


  在Flyer游戏场景中,我们将看到太空飞船基于头部的旋转来调整自身位置,具体参考FlyerMovementController:

  C#脚本:

  1. Quaternion headRotation = InputTracking.GetLocalRotation (VRNode.Head);
  2. m_TargetMarker.position = m_Camera.position + (headRotation * Vector3.forward) * m_DistanceFromCamera;
复制代码

Unity VR游戏开发干货教程:VR中的交互方式 ...


  在VR游戏中使用触摸板和键盘进行交互

  Gear VR在头戴设备的侧边配备了一个触摸板。Unity把这个触摸板当做鼠标来使用,所以我们可以使用以下方法:

  Unity - Scripting API: Input.mousePosition

  Unity - Scripting API: Input.GetMouseButtonDown

  Unity - Scripting API: Input.GetMouseButtonUp

  在使用Gear VR时,开发者可能会希望从触摸板中获取swipe数据。我们提供了一个名为VRInput的示例脚本,可以处理swipe,触碰和双触。此外它还支持方向键和键盘上的左Ctrl键(在Unity中的默认输入术语是Fire1),或者是鼠标上的左键,以此来处罚swipe和触摸。

  在Unity Editor中,我们可能会希望使用DK2来测试Gear VR的内容。因为目前暂时无法直接从Unity直接关联到Gear VR进行测试。考虑到Gear VR的触摸板作用跟鼠标类似,我们可以考虑使用鼠标来模拟输入。当用户佩戴HMD设备时操控键盘会更容易,因此VRInput同时也会讲方向键操作处理成swipe,将Left-Ctrl(Fire1)处理成触碰。

  在使用游戏手柄时,左侧的stick可以用作swipe,其中的某个按键可以用作触碰。

  关于如何处理swipe,可以参考VRSampleScenes/Scenes/Examples/Touchpad

  以下是ExampleTouchpad脚本,其中根据swipe的方向将AddTorque方法作用于一个刚体,从而让对象旋转。

  C#脚本:

  1. using UnityEngine;
  2. using VRStandardAssets.Utils;
  3. namespace VRStandardAssets.Examples
  4. {
  5. // This script shows a simple example of how
  6. // swipe controls can be handled.
  7. public class ExampleTouchpad : MonoBehaviour
  8. {
  9. [SerializeField] private float m_Torque = 10f;
  10. [SerializeField] private VRInput m_VRInput; 
  11. [SerializeField] private Rigidbody m_Rigidbody; 
  12. private void OnEnable()
  13. {
  14. m_VRInput.OnSwipe += HandleSwipe;
  15. }
  16. private void OnDisable()
  17. {
  18. m_VRInput.OnSwipe -= HandleSwipe;
  19. }

  20. //Handle the swipe events by applying AddTorque to the Ridigbody
  21. private void HandleSwipe(VRInput.SwipeDirection swipeDirection)
  22. {
  23. switch (swipeDirection)
  24. {
  25. case VRInput.SwipeDirection.NONE:
  26. break;
  27. case VRInput.SwipeDirection.UP:
  28. m_Rigidbody.AddTorque(Vector3.right * m_Torque);
  29. break;
  30. case VRInput.SwipeDirection.DOWN:
  31. m_Rigidbody.AddTorque(-Vector3.right * m_Torque);
  32. break;
  33. case VRInput.SwipeDirection.LEFT:
  34. m_Rigidbody.AddTorque(Vector3.up * m_Torque);
  35. break;
  36. case VRInput.SwipeDirection.RIGHT:
  37. m_Rigidbody.AddTorque(-Vector3.up * m_Torque);
  38. break;
  39. }
  40. }
  41. }
  42. }
复制代码

  VR Samples项目中的VRInput示例

  正如上面所提到的,我们所有的示例游戏都使用VRInput来处理触摸屏和键盘的输入。Maze游戏中的摄像机也会对swipe作出响应:

  Maze

  在这个场景中,CameraOrbit对swipe进行监听,从而允许对视点进行调整:

  C#脚本:

  1. private void OnEnable ()
  2. {
  3. m_VrInput.OnSwipe += HandleSwipe;
  4. }
  5. private void HandleSwipe(VRInput.SwipeDirection swipeDirection)
  6. {
  7. // If the game isn't playing or the camera is fading, return and don't handle the swipe.
  8. if (!m_MazeGameController.Playing)
  9. return;
  10. if (m_CameraFade.IsFading)
  11. return;
  12. // Otherwise start rotating the camera with either a positive or negative increment.
  13. switch (swipeDirection)
  14. {
  15. case VRInput.SwipeDirection.LEFT:
  16. StartCoroutine(RotateCamera(m_RotationIncrement));
  17. break;
  18. case VRInput.SwipeDirection.RIGHT:
  19. StartCoroutine(RotateCamera(-m_RotationIncrement));
  20. break;
  21. }
  22. }
复制代码
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity VR游戏开发干货教程:VR中的交互方式 的相关文章

  • Unity—UGUI

    每日一句 读数 学习 去更远的地方 才能摆脱那些你不屑一顾的圈子 目录 InputFiled输入框 例 用户名和密码 Toggle组件 案例 冷却效果 InputFiled输入框 Text Component 输入文本组件 Text输入内容
  • unity game界面按下play会不断闪烁,按下暂停键(pause)或者中止/下一步(step),game界面的画面会接连变化

    没找到答案 改了两个下午的程序 改完还是这样 后来发现是FixedUpdate Update与OnDrawGizmos的问题 OnDrawGizmos是每帧都会绘制 用FixedUpdate理所当然就那啥了 分析的时候 就突然想到是不是这俩
  • 【Unity Shader】屏幕后处理1.0:调整亮度/饱和度/对比度

    1 Unity中实现屏幕特效的基本步骤 什么叫屏幕后处理 Screen post processing effects 渲染完整个场景得到屏幕图像后对图像进行一系列操作 实现各种屏幕特效 这一步我们可以添加很多例如景深 Depth of F
  • Unity3d Terrain地形制作系列(一)

    游戏简单地形 地形制作 地形制作 第一步在场景里加载一个地形对象 第二步 我们在属性面板里找到绘制地形 然后选择Set Height 绘制高度 应该我们要制作低凹的效果 所有先让他有个高度 不然是不能实现低凹的效果 如图 我们然后选择绘制地
  • 蒙特卡洛积分、重要性采样、低差异序列

    渲染公式 渲染的目标在于计算周围环境的光线有多少从表面像素点反射到相机视口中 要计算总的反射光 每个入射方向的贡献 必须将他们在半球上相加 为入射光线 与法线 的夹角 为方便计算可以使用法线向量和入射向量 单位化 的乘积表示 对于基于图像的
  • Unity 安卓打包

    Unity打包的方式有很多种 自动打包和手动打包 今天小弟就鼓捣鼓捣unity手动打包 如果想动态打包的话 可以去看其他大佬的帖帖哈 unity打包先配置环境 下载unity的时候可以顺道把unity的安卓包下载下来 如果忘了也没事 可以从
  • Unity中级客户端开发工程师的进阶之路

    上期UWA技能成长系统之 Unity高级客户端开发工程师的进阶之路 得到了很多Unity开发者的肯定 通过系统的学习 可以掌握游戏性能瓶颈定位的方法和常见的CPU GPU 内存相关的性能优化方法 UWA技能成长系统是UWA根据学员的职业发展
  • Unity动画系统详解

    目录 动画编辑器 编辑器面板 动画复用 前言 人形重定向动画 Humanoid 通用动画 Generic 旧版本动画 Legacy 动画控制器 系统状态 切换条件 状态机脚本 IK动画 反向动力学 BlendTree 混合树 Animato
  • Unity与Android的Back键冲突解决

    Unity与Android的Back键冲突解决 上一篇的最后留下了两个问题 Unity视图下横屏闪退 Unity视图下Android无法响应back返回上一activity 对于第一个问题 应该是Unity横屏下视图的某些设置跟Androi
  • unity中创建询问弹出窗口

    在开发过程中进程会遇到需要弹出一个窗口询问用户是否进行的操作 今天就来制作一个这样弹出窗口 然后根据弹出窗口的选择内容不同进行不同的操作 本例中主要是为了删除一个数据 而在删除数据操作前需要得到用户的一个确认操作 这里面主要用到了Notif
  • unity工程崩溃资源找回

    1 Unity死机未保存场景 当你在Unity中编辑场景 突然死机时 可以在项目文件目录中找到Temp文件夹 双击文件夹 找到 Backupscenes文件夹 把后缀为 backup的文件后缀改为 unity 然后拖进Unity的Proje
  • 【Unity】按Esc进入操作菜单

    本文章是基于如下视频的自我总结 https www youtube com watch v JivuXdrIHK0 步骤如下 1 在Canvas 界面添加一个Panel Panel中添加一个按钮 调整按钮的大小为合适大小 调整字体的大小为合
  • unity实现鼠标右键控制视角

    主要实现的功能是相机跟随主角 鼠标右击移动后 相机的视角会旋转 思路 在主角里创建空的子物体 把相机绑在空物体上 通过旋转空物体来实现视角的旋转 要把相机调整到适当位置 代码如下 public float rotateSpeed 100 设
  • Unity旋转以及万向锁问题

    我之前研读了一些关于unity旋转相关的博客 一直想抽个时间写个总结 但是由于实习太忙一直没有写 趁着今天请了假晚上有时间把这段时间一些学习心得写出来 Unity inspector面板中的Rotation 在unity中 想必大家最先接触
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    Unity 运行时创建线 贝塞尔的运用 1 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线 2 原理介绍 2 1 曲线的创建 unity建立网格曲线可以参考 Unity程序化网格体 的实现方法 主要分为顶点 三角面 U
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    Unity 运行时创建线 贝塞尔的运用 1 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线 2 原理介绍 2 1 曲线的创建 unity建立网格曲线可以参考 Unity程序化网格体 的实现方法 主要分为顶点 三角面 U
  • Unity中URP下的指数雾

    文章目录 前言 一 指数雾 雾效因子 1 FOG EXP 2 FOG EXP2 二 MixFog 1 ComputeFogIntensity 雾效强度计算 2 lerp fogColor fragColor fogIntensity 雾效颜
  • 游戏开发常见操作梳理之NPC任务系统

    多数游戏存在任务系统 接下来介绍通过NPC触发任务的游戏制作代码 using System Collections using System Collections Generic using UnityEngine
  • 游戏开发常见操作梳理系列之——玩家信息的显示系统

    在游戏中 有不少游戏在左上角会出现玩家的头像和等级以及血量 这就是玩家的信息显示系统 那么这些是如何制作的呢 接下来我将讲讲代码的操作 其它操作我会在其它笔记中一一说明 敬请期待 信息的显示相当简单就是控制一些UI 然后在其它系统里面填写相
  • 游戏开发常用实践操作之按动任意键触发

    接下来一些笔记会对于一些大大小小的实践操作进行记录 希望对你有所帮助 在游戏中 我们经常会遇到一些按动任意键触发的操作 接下来展示核心代码 以下是对于Unity中的操作 使用的UI是NGUI 对于核心操作没有影响 你可以自己置换 void

随机推荐

  • STM32F4配置内部时钟(HSI)

    STM32F4配置内部时钟 半年多没更新了 xff0c 今天配置F4的时候内部时钟问题整了2个小时 xff0c 记录下这个坑 有些板子由于没有贴外部晶振 xff0c 所以代码运行起来的时候时钟就会出问题 xff0c 本来配置的中断是1ms实
  • 无人机加速计、气压计、GPS数据融合

    加速计 气压计 GPS数据融合 在无人机控制当中 xff0c 传感器的参与那是必不可少的 xff0c 特别是陀螺仪 xff0c 最经典的为MPU6050 xff0c 目前大部分的无人机都是用的这个器件 熟悉MPU6050的都知道 xff0c
  • ROS串口编程学习笔记

    串口是一种设备间常用的通讯接口 xff0c 本文将记录如何在ROS上使用其提供的serial包进行串口通信 首先 xff0c 这里要引入一个名称为serial的包 xff0c 这个包的安装命令为 xff1a sudo apt get ins
  • github国内镜像代理【持续更新】

    整理github国内代理 xff08 镜像站 xff09 会不定期持续更新 不过由于我都是优先从gitee上找资源 xff0c 所以有时会更新的比较慢 域名更新时间备注https kgithub com2023 03 14 已失效备注 以下
  • android适配ipv6,请求慢?

    先贴一篇我们经常能搜索到的解决方案 xff1a Android 在 4G 下访问 IPV6 慢的解决方案 文章很有参考意义 xff0c 但也并不是所有请求慢的的原因 xff01 本文是另一种原因 有兴趣就继续往下看一看 使用的okhttp框
  • 总结一下__declspec(dllimport)的作用

    作者 xff1a 朱金灿 来源 xff1a http blog csdn net clever101 是时候总结一下 declspec dllimport 的作用了 可能有人会问 xff1a declspec dllimport 和 dec
  • Autojs初试

    1 环境布置 AutoJs 目前能找到的 autojs的版本是 Autojs 4 4 1 7 pro pojie 8pro 需付费 VsCode VScode 安装对应版本插件 xff0c autojs 和autojs pro需要插件不同
  • APK反编译流程学习[1]

    1 获得 classes dex classes dex是由java文件编译再通过dx工具打包而成的 将apk重命名为zip或者rar后缀 xff0c 进行解压 里面的文件基本都是乱码 xff0c 如下图 xff1a 2 使用dex2jar
  • c csv 保存函数

    include lt stdio h gt include lt stdlib h gt include lt string gt int save csv const char file path unsigned char data i
  • 坐标系变换推导(欧拉角、方向余弦矩阵、四元数)+代码解析

    一 为什么选择四元数 描述两个坐标系之间的变换关系主要有几个方法 1 欧拉角法 存在奇异性和万向锁而且三个轴旋转的顺序不好定 2 方向余弦矩阵法 翻译为Directional cosine matrix xff0c 简称DCM xff0c
  • 如何从正确的原理图生成PCB图

    首先 编译sch文件 Project 下面的第二个选项 之后生成网表文件 Design Netlist for Project 之后在PCB文件里面画板子形状 CRTL 43 M 是测量长度 选择你画的板子大小的封闭图形边界线 在Mecha
  • python中try except处理程序异常的三种常用方法

    转载自 xff1a http www pythontab com html 2013 pythonjichu 0204 210 html 如果你在写python程序时遇到异常后想进行如下处理的话 一般用try来处理异常 xff0c 假设有下
  • 好久之前看过的BOOT0与BOOT1设置问题

    好久之前看过关于BOOT0与BOOT1问题 xff0c 用于在不同地方启动 xff0c 这回又碰到了 stm32的flash读保护了 用户闪存 61 内置的flash 掉电不易失 SRAM 61 芯片的内部的RAM 就是所谓的内存 ROM
  • 论文中的引用的超链接格式

    引用自 xff1a http jingyan baidu com article 4e5b3e1952739291901e2495 html 百度经验 http jingyan baidu com article 4e5b3e1952739
  • 使用ST-Link Utility去除STM32芯片读写保护

    转载学习自 xff1a http blog csdn net hxiaohai article details 78546431 locationNum 61 10 amp fps 61 1 问题 xff1a 使用ISP J Link ST
  • I2C的 SCL和SDA为什么要上拉

    因为允许把多个I2C总线器件连接到总线上 xff0c 连接到I2C总线上的器件是漏极开路或集电极开路的 xff0c 可以实现线与功能 同时 xff0c 因为接了上拉电阻 xff0c 在总线空闲期间 xff0c SDA和SCL都是高电平 xf
  • 略谈中国软件产品化的路线图

    作者 xff1a 朱金灿 来源 xff1a http blog csdn net clever101 预计这篇要挨一些砖头 xff0c 但既然说了 xff0c 就不怕挨一些砖头 进入正题 蒙圣光大侠的一篇 软件产品化 国内IT人之痛 引发了
  • STM32的HAL库的 I2C和UART使用函数,几个好用的

    HAL StatusTypeDef I2C Write uint8 t pBuffer uint8 t DeviceAddr uint8 t RegisterAddr uint16 t NumByteToWrite uint8 t data
  • 解析一波csdn.net的图片链接

    研究一波csdn net的图片链接 例子如下 https img blog csdnimg cn 0380d37492324ec58cc898470b100679 png x oss process 61 image watermark t
  • Unity VR游戏开发干货教程:VR中的交互方式

    游戏程序 平台类型 虚拟VR 程序设计 编程语言 引擎 SDK Unity3D 2D GameRes游资网授权发布 文 王寒 在VR项目中 xff0c 我们需要在用户 凝视 某个物体时将其激活 在VRSamples中 xff0c 我们构建了