https://blog.csdn.net/qq_15807167/article/details/52048998?locationNum=8&fps=1

阅读数:9716

最近有点忙,只有挤时间去了解VR这方面的Demo了,之前关注了一个Android平台的视频VR的demo研读的差不多了,现在开始关注Unity3d建造VR游戏环境的demo. 
Android下demo例子地址。 
https://github.com/ashqal/MD360Player4AndroidVR视频播放demo 
https://github.com/ejeinc/RajawaliCardboardExamplecardboard的demo

正题

前提界面介绍

初始界面。 

主界面 

飞机游戏的模型界面 

迷宫的模型界面 

射击场景有两个 一个是180度的视角比较远,一个是360度的视角(等距离) 

 了解结构

  • 我们从飞机那个unity的工程中来看,其Hierarchy的结构(主要讲重点部分) 
  • 首先我们从相机开始说起 
    • 首先我们从每个C#脚本去看实现的过程 

      VREyeRaycaster.cs
using System;
using UnityEngine; namespace VRStandardAssets.Utils
{
// In order to interact with objects in the scene
// this class casts a ray into the scene and if it finds
// a VRInteractiveItem it exposes it for other classes to use.
// This script should be generally be placed on the camera.
//为了与场景中的物体相互作用
//这个类投射到场景中的光线,如果它发现
// vrinteractiveitem它暴露了它的其他类使用。
//这个脚本应该被放置在相机上。
public class VREyeRaycaster : MonoBehaviour
{
public event Action<RaycastHit> OnRaycasthit; // This event is called every frame that the user's gaze is over a collider. [SerializeField] private Transform m_Camera;
[SerializeField] private LayerMask m_ExclusionLayers; // Layers to exclude from the raycast. 光线投射的层
[SerializeField] private Reticle m_Reticle; // The reticle, if applicable.网线
[SerializeField] private VRInput m_VrInput; // Used to call input based events on the current VRInteractiveItem.
[SerializeField] private bool m_ShowDebugRay; // Optionally show the debug ray.是否显示调试光线
[SerializeField] private float m_DebugRayLength = 5f; // Debug ray length.光线的长度
[SerializeField] private float m_DebugRayDuration = 1f; // How long the Debug ray will remain visible.光线存活时间
[SerializeField] private float m_RayLength = 500f; // How far into the scene the ray is cast.光线投射到场景的距离 private VRInteractiveItem m_CurrentInteractible; //The current interactive item 当前交互点
private VRInteractiveItem m_LastInteractible; //The last interactive item 最后交互点 //从其他类中获得当前的交互点
// Utility for other classes to get the current interactive item
public VRInteractiveItem CurrentInteractible
{
get { return m_CurrentInteractible; }
} private void OnEnable()
{
m_VrInput.OnClick += HandleClick;
m_VrInput.OnDoubleClick += HandleDoubleClick;
m_VrInput.OnUp += HandleUp;
m_VrInput.OnDown += HandleDown;
} private void OnDisable ()
{
m_VrInput.OnClick -= HandleClick;
m_VrInput.OnDoubleClick -= HandleDoubleClick;
m_VrInput.OnUp -= HandleUp;
m_VrInput.OnDown -= HandleDown;
} //unity的更新方法
private void Update()
{
EyeRaycast();
} private void EyeRaycast()
{ //如果是必要的话,则显示调试线(在unity上设置 )
// Show the debug ray if required
if (m_ShowDebugRay)
{
Debug.DrawRay(m_Camera.position, m_Camera.forward * m_DebugRayLength, Color.blue, m_DebugRayDuration);
}
//创建相机前方的光线
// Create a ray that points forwards from the camera.
Ray ray = new Ray(m_Camera.position, m_Camera.forward);
RaycastHit hit;
//这里主要判断前方光线的展示与否
// Do the raycast forweards to see if we hit an interactive item
if (Physics.Raycast(ray, out hit, m_RayLength, ~m_ExclusionLayers))
{
VRInteractiveItem interactible = hit.collider.GetComponent<VRInteractiveItem>(); //attempt to get the VRInteractiveItem on the hit object
m_CurrentInteractible = interactible; // If we hit an interactive item and it's not the same as the last interactive item, then call Over
if (interactible && interactible != m_LastInteractible)
interactible.Over(); // Deactive the last interactive item
if (interactible != m_LastInteractible)
DeactiveLastInteractible(); m_LastInteractible = interactible; // Something was hit, set at the hit position.
if (m_Reticle)
m_Reticle.SetPosition(hit); if (OnRaycasthit != null)
OnRaycasthit(hit);
}
else
{
// Nothing was hit, deactive the last interactive item.
DeactiveLastInteractible();
m_CurrentInteractible = null; // Position the reticle at default distance.
if (m_Reticle)
m_Reticle.SetPosition();
}
} private void DeactiveLastInteractible()
{
if (m_LastInteractible == null)
return; m_LastInteractible.Out();
m_LastInteractible = null;
} private void HandleUp()
{
if (m_CurrentInteractible != null)
m_CurrentInteractible.Up();
} private void HandleDown()
{
if (m_CurrentInteractible != null)
m_CurrentInteractible.Down();
} private void HandleClick()
{
if (m_CurrentInteractible != null)
m_CurrentInteractible.Click();
} private void HandleDoubleClick()
{
if (m_CurrentInteractible != null)
m_CurrentInteractible.DoubleClick(); }
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150

VRCameraUi.cs

 using System;
using UnityEngine; namespace VRStandardAssets.Utils
{ //这类保证UI(如网线和选择吧)
//正确地设置。
// This class ensures that the UI (such as the reticle and selection bar)
// are set up correctly.
public class VRCameraUI : MonoBehaviour
{
[SerializeField] private Canvas m_Canvas; // Reference to the canvas containing the UI.包含用户界面的画布的参考。 private void Awake()
{
// Make sure the canvas is on.确保画布上。
m_Canvas.enabled = true; // Set its sorting order to the front.把它的排序顺序设置为前面。
m_Canvas.sortingOrder = Int16.MaxValue; // Force the canvas to redraw so that it is correct before the first render.在第一次渲染前 力将会重绘。
Canvas.ForceUpdateCanvases();
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

SelectionRadial.cs

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System; namespace VRStandardAssets.Utils
{
// This class is used to control a radial bar that fills
// up as the user holds down the Fire1 button. When it has
// finished filling it triggers an event. It also has a
// coroutine which returns once the bar is filled.
public class SelectionRadial : MonoBehaviour
{
public event Action OnSelectionComplete; // This event is triggered when the bar has filled. [SerializeField] private float m_SelectionDuration = 2f; // How long it takes for the bar to fill.
[SerializeField] private bool m_HideOnStart = true; // Whether or not the bar should be visible at the start.
[SerializeField] private Image m_Selection; // Reference to the image who's fill amount is adjusted to display the bar.
[SerializeField] private VRInput m_VRInput; // Reference to the VRInput so that input events can be subscribed to. private Coroutine m_SelectionFillRoutine; // Used to start and stop the filling coroutine based on input.
private bool m_IsSelectionRadialActive; // Whether or not the bar is currently useable.
private bool m_RadialFilled; // Used to allow the coroutine to wait for the bar to fill. public float SelectionDuration { get { return m_SelectionDuration; } } private void OnEnable()
{
m_VRInput.OnDown += HandleDown;
m_VRInput.OnUp += HandleUp;
} private void OnDisable()
{
m_VRInput.OnDown -= HandleDown;
m_VRInput.OnUp -= HandleUp;
} private void Start()
{
// Setup the radial to have no fill at the start and hide if necessary.
m_Selection.fillAmount = 0f; if(m_HideOnStart)
Hide();
} public void Show()
{
m_Selection.gameObject.SetActive(true);
m_IsSelectionRadialActive = true;
} public void Hide()
{
m_Selection.gameObject.SetActive(false);
m_IsSelectionRadialActive = false; // This effectively resets the radial for when it's shown again.
m_Selection.fillAmount = 0f;
} private IEnumerator FillSelectionRadial()
{
// At the start of the coroutine, the bar is not filled.
m_RadialFilled = false; // Create a timer and reset the fill amount.
float timer = 0f;
m_Selection.fillAmount = 0f; // This loop is executed once per frame until the timer exceeds the duration.
while (timer < m_SelectionDuration)
{
// The image's fill amount requires a value from 0 to 1 so we normalise the time.
m_Selection.fillAmount = timer / m_SelectionDuration; // Increase the timer by the time between frames and wait for the next frame.
timer += Time.deltaTime;
yield return null;
} // When the loop is finished set the fill amount to be full.
m_Selection.fillAmount = 1f; // Turn off the radial so it can only be used once.
m_IsSelectionRadialActive = false; // The radial is now filled so the coroutine waiting for it can continue.
m_RadialFilled = true; // If there is anything subscribed to OnSelectionComplete call it.
if (OnSelectionComplete != null)
OnSelectionComplete();
} public IEnumerator WaitForSelectionRadialToFill ()
{
// Set the radial to not filled in order to wait for it.
m_RadialFilled = false; // Make sure the radial is visible and usable.
Show (); // Check every frame if the radial is filled.
while (!m_RadialFilled)
{
yield return null;
} // Once it's been used make the radial invisible.
Hide ();
} private void HandleDown()
{
// If the radial is active start filling it.
if (m_IsSelectionRadialActive)
{
m_SelectionFillRoutine = StartCoroutine(FillSelectionRadial());
}
} private void HandleUp()
{
// If the radial is active stop filling it and reset it's amount.
if (m_IsSelectionRadialActive)
{
if(m_SelectionFillRoutine != null)
StopCoroutine(m_SelectionFillRoutine); m_Selection.fillAmount = 0f;
}
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148

Reticle.cs

using UnityEngine;
using UnityEngine.UI; namespace VRStandardAssets.Utils
{
// The reticle is a small point at the centre of the screen.
// It is used as a visual aid for aiming. The position of the
// reticle is either at a default position in space or on the
// surface of a VRInteractiveItem as determined by the VREyeRaycaster.
public class Reticle : MonoBehaviour
{
[SerializeField] private float m_DefaultDistance = 5f; // The default distance away from the camera the reticle is placed.
[SerializeField] private bool m_UseNormal; // Whether the reticle should be placed parallel to a surface.
[SerializeField] private Image m_Image; // Reference to the image component that represents the reticle.
[SerializeField] private Transform m_ReticleTransform; // We need to affect the reticle's transform.
[SerializeField] private Transform m_Camera; // The reticle is always placed relative to the camera. private Vector3 m_OriginalScale; // Since the scale of the reticle changes, the original scale needs to be stored.
private Quaternion m_OriginalRotation; // Used to store the original rotation of the reticle. public bool UseNormal
{
get { return m_UseNormal; }
set { m_UseNormal = value; }
} public Transform ReticleTransform { get { return m_ReticleTransform; } } private void Awake()
{
// Store the original scale and rotation.
m_OriginalScale = m_ReticleTransform.localScale;
m_OriginalRotation = m_ReticleTransform.localRotation;
} public void Hide()
{
m_Image.enabled = false;
} public void Show()
{
m_Image.enabled = true;
} // This overload of SetPosition is used when the the VREyeRaycaster hasn't hit anything.
public void SetPosition ()
{
// Set the position of the reticle to the default distance in front of the camera.
m_ReticleTransform.position = m_Camera.position + m_Camera.forward * m_DefaultDistance; // Set the scale based on the original and the distance from the camera.
m_ReticleTransform.localScale = m_OriginalScale * m_DefaultDistance; // The rotation should just be the default.
m_ReticleTransform.localRotation = m_OriginalRotation;
} // This overload of SetPosition is used when the VREyeRaycaster has hit something.
public void SetPosition (RaycastHit hit)
{
m_ReticleTransform.position = hit.point;
m_ReticleTransform.localScale = m_OriginalScale * hit.distance; // If the reticle should use the normal of what has been hit...
if (m_UseNormal)
// ... set it's rotation based on it's forward vector facing along the normal.
m_ReticleTransform.rotation = Quaternion.FromToRotation (Vector3.forward, hit.normal);
else
// However if it isn't using the normal then it's local rotation should be as it was originally.
m_ReticleTransform.localRotation = m_OriginalRotation;
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

VR CameraaFade

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio; namespace VRStandardAssets.Utils
{
// This class is used to fade the entire screen to black (or
// any chosen colour). It should be used to smooth out the
// transition between scenes or restarting of a scene.
public class VRCameraFade : MonoBehaviour
{
public event Action OnFadeComplete; // This is called when the fade in or out has finished. [SerializeField] private Image m_FadeImage; // Reference to the image that covers the screen.
[SerializeField] private AudioMixerSnapshot m_DefaultSnapshot; // Settings for the audio mixer to use normally.
[SerializeField] private AudioMixerSnapshot m_FadedSnapshot; // Settings for the audio mixer to use when faded out.
[SerializeField] private Color m_FadeColor = Color.black; // The colour the image fades out to.
[SerializeField] private float m_FadeDuration = 2.0f; // How long it takes to fade in seconds.
[SerializeField] private bool m_FadeInOnSceneLoad = false; // Whether a fade in should happen as soon as the scene is loaded.
[SerializeField] private bool m_FadeInOnStart = false; // Whether a fade in should happen just but Updates start. private bool m_IsFading; // Whether the screen is currently fading.
private float m_FadeStartTime; // The time when fading started.
private Color m_FadeOutColor; // This is a transparent version of the fade colour, it will ensure fading looks normal. public bool IsFading { get { return m_IsFading; } } private void Awake()
{
m_FadeOutColor = new Color(m_FadeColor.r, m_FadeColor.g, m_FadeColor.b, 0f);
m_FadeImage.enabled = true;
} private void Start()
{
// If applicable set the immediate colour to be faded out and then fade in.
if (m_FadeInOnStart)
{
m_FadeImage.color = m_FadeColor;
FadeIn(true);
}
} private void OnLevelWasLoaded()
{
// If applicable set the immediate colour to be faded out and then fade in.
if (m_FadeInOnSceneLoad)
{
m_FadeImage.color = m_FadeColor;
FadeIn(true);
}
} // Since no duration is specified with this overload use the default duration.
public void FadeOut(bool fadeAudio)
{
FadeOut(m_FadeDuration, fadeAudio);
} public void FadeOut(float duration, bool fadeAudio)
{
// If not already fading start a coroutine to fade from the fade out colour to the fade colour.
if (m_IsFading)
return;
StartCoroutine(BeginFade(m_FadeOutColor, m_FadeColor, duration)); // Fade out the audio over the same duration.
if(m_FadedSnapshot && fadeAudio)
m_FadedSnapshot.TransitionTo (duration);
} // Since no duration is specified with this overload use the default duration.
public void FadeIn(bool fadeAudio)
{
FadeIn(m_FadeDuration, fadeAudio);
} public void FadeIn(float duration, bool fadeAudio)
{
// If not already fading start a coroutine to fade from the fade colour to the fade out colour.
if (m_IsFading)
return;
StartCoroutine(BeginFade(m_FadeColor, m_FadeOutColor, duration)); // Fade in the audio over the same duration.
if(m_DefaultSnapshot && fadeAudio)
m_DefaultSnapshot.TransitionTo (duration);
} public IEnumerator BeginFadeOut (bool fadeAudio)
{
// Fade out the audio over the default duration.
if(m_FadedSnapshot && fadeAudio)
m_FadedSnapshot.TransitionTo (m_FadeDuration); yield return StartCoroutine(BeginFade(m_FadeOutColor, m_FadeColor, m_FadeDuration));
} public IEnumerator BeginFadeOut(float duration, bool fadeAudio)
{
// Fade out the audio over the given duration.
if(m_FadedSnapshot && fadeAudio)
m_FadedSnapshot.TransitionTo (duration); yield return StartCoroutine(BeginFade(m_FadeOutColor, m_FadeColor, duration));
} public IEnumerator BeginFadeIn (bool fadeAudio)
{
// Fade in the audio over the default duration.
if(m_DefaultSnapshot && fadeAudio)
m_DefaultSnapshot.TransitionTo (m_FadeDuration); yield return StartCoroutine(BeginFade(m_FadeColor, m_FadeOutColor, m_FadeDuration));
} public IEnumerator BeginFadeIn(float duration, bool fadeAudio)
{
// Fade in the audio over the given duration.
if(m_DefaultSnapshot && fadeAudio)
m_DefaultSnapshot.TransitionTo (duration); yield return StartCoroutine(BeginFade(m_FadeColor, m_FadeOutColor, duration));
} private IEnumerator BeginFade(Color startCol, Color endCol, float duration)
{
// Fading is now happening. This ensures it won't be interupted by non-coroutine calls.
m_IsFading = true; // Execute this loop once per frame until the timer exceeds the duration.
float timer = 0f;
while (timer <= duration)
{
// Set the colour based on the normalised time.
m_FadeImage.color = Color.Lerp(startCol, endCol, timer / duration); // Increment the timer by the time between frames and return next frame.
timer += Time.deltaTime;
yield return null;
} // Fading is finished so allow other fading calls again.
m_IsFading = false; // If anything is subscribed to OnFadeComplete call it.
if (OnFadeComplete != null)
OnFadeComplete();
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168

ReturnToMainMenu.cs

 using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement; namespace VRStandardAssets.Utils
{
// This class simply allows the user to return to the main menu.
public class ReturnToMainMenu : MonoBehaviour
{
[SerializeField] private string m_MenuSceneName = "MainMenu"; // The name of the main menu scene.
[SerializeField] private VRInput m_VRInput; // Reference to the VRInput in order to know when Cancel is pressed.
[SerializeField] private VRCameraFade m_VRCameraFade; // Reference to the script that fades the scene to black. private void OnEnable ()
{
m_VRInput.OnCancel += HandleCancel;
} private void OnDisable ()
{
m_VRInput.OnCancel -= HandleCancel;
} private void HandleCancel ()
{
StartCoroutine (FadeToMenu ());
} private IEnumerator FadeToMenu ()
{
// Wait for the screen to fade out.
yield return StartCoroutine (m_VRCameraFade.BeginFadeOut (true)); // Load the main menu by itself.
SceneManager.LoadScene(m_MenuSceneName, LoadSceneMode.Single);
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

VR Tracking Reset.cs

 using UnityEngine;
using UnityEngine.VR; namespace VRStandardAssets.Utils
{
// This class simply insures the head tracking behaves correctly when the application is paused.
public class VRTrackingReset : MonoBehaviour
{
private void OnApplicationPause(bool pauseStatus)
{
InputTracking.Recenter();
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

以上是相机中的C#脚步代码,本来想全部注释的,后来发现英文解释很全,这里大家看英文介绍就好。有空再写环境的demo实现。

版权声明:商业用途请联系博主,非商业转载请标明出处。 https://blog.csdn.net/qq_15807167/article/details/52048998

Unity3D关于VR的Demo(一)的更多相关文章

  1. Unity3D for VR 学习(7): 360°全景照片

    在VR应用中,有一个相对简单的虚拟现实体验,那就是360°全景照片浏览器, 他可以使得手机拍照的”全景”照片,  得以”恢复”当时拍照的场景全貌,  这个创意的确比单纯的2d图片更有震撼力一些,故本文 ...

  2. Unity3D for VR 学习(3): 暴风魔镜PC Input小改造–自己动手、丰衣足食

    在做手游的时候,80%时间是在PC调试的,例如业务逻辑.AI算法.核心玩法等. 拿到魔镜提供的demo,晕了,必须得安装到Android机器上,才能调试,究其原因,有三: 需要用到手机陀螺仪 需要用到 ...

  3. Unity3D for VR 学习(2): 暴风魔镜框架探索

    学习一个新技术,有三个法宝: 法宝1: 掌握厂家提供的用户API手册 法宝2: 掌握厂家提供的demo样例 法宝3:<每个研发人员都应树立的一个demo模式> 故,学习魔镜4技术,亦如是也 ...

  4. [Unity3D]做个小Demo学习Input.touches

    [Unity3D]做个小Demo学习Input.touches 学不如做,下面用一个简单的Demo展示的Input.touches各项字段,有图有真相. 本项目已发布到Github,地址在(https ...

  5. 菜鸟在线教你用Unity3D开发VR版的Hello World

    大家好,我是菜鸟在线的小编.这篇短文将告诉大家如何用Unity3D开发VR版的Hello World. 1开启SteamVR并连接Vive设备 (a)登录Steam客户端,并点击右上角的VR按钮,这时 ...

  6. Unity3D for VR 学习(9): Unity Shader 光照模型 (illumination model)

    关于光照模型 所谓模型,一般是由学术算法发起, 经过大量实际数据验证而成的可靠公式 现在还记得2009年做TD-SCDMA移动通信算法的时候,曾经看过自由空间传播模型(Free space propa ...

  7. Unity3D for VR 学习(8): Unity Shader概述

    从西安到北京高铁上,一位VR老外团队的华人leader对VR技术做了画龙点睛: “3D游戏的核心部分在Render, 国内很多团队美术.程序中间缺失严重.所以3d游戏做不好. VR这块更是至关重要.” ...

  8. Unity3D for VR 学习(6): 再次温故知新-3D数学

    一年前,系统学习过3D数学,并记录了一篇博客<C#程序员整理的Unity 3D笔记(十):Unity3D的位移.旋转的3D数学模型>. 一年后,再次温习之. 坐标系:Unity3D使用左手 ...

  9. Unity2016 Unity3D开发VR游戏的经验

    http://z.youxiputao.com/articles/8313 在4月12日的Unite 2016大会上,暴风魔镜高级产品经理吴涛分享他用Unity3D开发VR游戏的经验,以下为分享实录: ...

随机推荐

  1. POJ-2336 Ferry Loading II(简单DP)

    Ferry Loading II Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3763 Accepted: 1919 Desc ...

  2. ubuntu16.04安装 lrzsz

    编译安装 root 账号登陆后,依次执行以下命令: tar zxvf lrzsz-.tar.gz cd lrzsz- ./configure make make install 上面安装过程默认把ls ...

  3. Django的视图与网址之加法计算

    在最新的Django2.1中,views.py中采用的地址映射方式发生了变化,通过一个加法运算我们来看一看. 方法一:在视图views.py中定义视图逻辑,求解两个数的加法运算:c = a + b,定 ...

  4. redis系列之数据库与缓存数据一致性解决方案

    redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略 写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以 ...

  5. ubuntu 添加用户到已存在的组

    sudo adduser 用户名 组名   sudo minicom –s 配置 minicom访问ttyUSB0没权限,发现属于dialout 组 james@james-OptiPlex-380: ...

  6. linux Service start

    1. crontab的方式 2. 服务的方式.该服务能够持续监测minerd是否在运行,如果没有在运行就会运行minerd:服务也可以做成开机自启动.该服务执行的内容如下,该服务是判断目标服务器的pa ...

  7. python startswith() 函数

    startswith() 作用:判断字符串是否以指定字符或子字符串开头 >>> s = "my name is ming" >>> >&g ...

  8. csrf攻击原理及如何防止csrf攻击

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,是一种对网站的恶意利用,通过伪装来自受信任用 ...

  9. ListView and gridview常用属性

    刷新:notifyDataSetChanged 1.gridview常用属性 GridView的一些特殊属性:   1.Android:numColumns=”auto_fit”   //GridVi ...

  10. 万恶之源 - Python数据类型二

    列表 列表的介绍  列表是python的基础数据类型之一 ,其他编程语言也有类似的数据类型. 比如JS中的数 组, java中的数组等等. 它是以[ ]括起来, 每个元素用' , '隔开而且可以存放各 ...