Unity VR Samples示例项目分析
核心脚本和对象
在VR场景中,我们需要激活我们正在看着的物体,高亮或者交互。在VRSamples中主要包括三个脚本:VREyeRaycaster, VRInput, 以及VRInteractiveItem。
VREyeRaycaster
VREyeRaycaster.png
该脚本需要和Main Camera关联。在每次调用Update()时,该脚本都会使用Physics.Raycast来投射一条射线,以确认该射线是否命中任何collider(碰撞体)。使用该脚本还可以排除特定的Layer。在某些场景中,我们可能为了性能考虑,把所有的可交互对象移到一个单独的层。
如果某个碰撞体被射线命中,那么该脚本将尝试在GameObject上找到一个VRInteractiveItem组件。来看下该类的主要代码:
// 从相机位置向前发射一条射线
Ray ray = new Ray(m_Camera.position, m_Camera.forward);
RaycastHit hit;
//做射线投射,看是否有物体相交
if (Physics.Raycast(ray, out hit, m_RayLength, ~m_ExclusionLayers))
{
VRInteractiveItem interactible = hit.collider.GetComponent(); //获取相交物体上的VRInteractiveItem组件
m_CurrentInteractible = interactible;
//如果相交物体跟上次的物体不同,那么判断悬停
if (interactible && interactible != m_LastInteractible)
interactible.Over();
// 停用上次相交物体,该函数内置空
if (interactible != m_LastInteractible)
DeactiveLastInteractible();
m_LastInteractible = interactible;
//有物体相交的话,瞄准星的位置要更新。在该函数中,会根据距离做缩放;使用相交物体的法线方向做旋转。
if (m_Reticle)
m_Reticle.SetPosition(hit);
//调用事件处理函数
if (OnRaycasthit != null)
OnRaycasthit(hit);
}
else
{
//没有相交物体,置空上次使用的可交互物体
DeactiveLastInteractible();
m_CurrentInteractible = null;
//把瞄准星放到默认位置
if (m_Reticle)
m_Reticle.SetPosition();
}
该类在OnEnable函数中和OnDisable函数中会把VRInteractiveItem上的处理事件函数与VRInput中的事件绑定起来(订阅事件)。
VRInput
image2.png
VRInput是个简单的类,可以判断用户在GearVR上(或是使用DK2时在PC上)所进行的一些简单操作,比如滑动、触碰、或双触。
VRInteractiveItem
我们可以把该组件添加到任何希望在VR场景中进行交互的GameObject上,在该物体上需要绑定一个碰撞体。
交互可视化元素SelectionRadial和SelectionSlider
我们同时利用了radial选择条(SelectionRadial),以及选择滑动条(SelectionSlider),这样用户就可以按住Fire1来确认某个交互:
image3.png
image4.png
当按住输入键时,选择条会进行填充,并在填充完整后分发OnSelectionComplete或OnBarFilled事件。关于此部分的代码,可以在SelectionRadial.cs和SelectionSlider.cs中找到,并进行了详细的注释。
在VR的世界里,从用户交互的角度看,用户需要时刻知道自己在做什么,而且可以掌控一切。通过这种“held input”的确认输入方式,可以确保用户不会出现误操作。
VR Sample项目中的各个场景分析
先来分析一下各个场景中对象和脚本的作用
Main