当激光击中物体并且用户按下控制器的后侧按钮时,我想用Gear VR控制器选择场景中的物体。我已经为控制器完成了光线投射和激光,它工作正常,但我找不到让选择工作的方法。代码如下,我也评论了我写的部分以及它应该做的事情。
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.
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 LineRenderer m_LineRenderer = null; // For supporting Laser Pointer
public bool ShowLineRenderer = true; // Laser pointer visibility
[SerializeField]
private Transform m_TrackingSpace = null; // Tracking space (for line renderer)
[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
private String m_IIName;
private string[] objArrayName1 = {"Clock","Train", "Chair", "Pant", "Bed", "BlueHat" };
private string[] objArrayName2 = { "BookOld", "Lambo", "NotebookGRN", "Airplane", "Cup1", "Teddy" };
private int phase = 0;
private short i = 0;
private OVRInput.Controller controller;
// 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;
}
private void Update()
{
EyeRaycast();
}
private void EyeRaycast()
{
// 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;
Vector3 worldStartPoint = Vector3.zero;
Vector3 worldEndPoint = Vector3.zero;
if (m_LineRenderer != null)
{
m_LineRenderer.enabled = ControllerIsConnected && ShowLineRenderer;
}
if (ControllerIsConnected && m_TrackingSpace != null)
{
Matrix4x4 localToWorld = m_TrackingSpace.localToWorldMatrix;
Quaternion orientation = OVRInput.GetLocalControllerRotation(Controller);
Vector3 localStartPoint = OVRInput.GetLocalControllerPosition(Controller);
Vector3 localEndPoint = localStartPoint + ((orientation * Vector3.forward) * 500.0f);
worldStartPoint = localToWorld.MultiplyPoint(localStartPoint);
worldEndPoint = localToWorld.MultiplyPoint(localEndPoint);
// Create new ray
ray = new Ray(worldStartPoint, worldEndPoint - worldStartPoint);
}
// 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
if (interactible)
{
worldEndPoint = hit.point;
}
m_CurrentInteractible = interactible;
//**************************************************** I started coding here (If the user selects an interactive object the we have to check if it's in phase A or B of the game *****************************************************************
if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger)) //If the user pressed the back side button of the controller
{
m_IIName = m_CurrentInteractible.name;
if (phase == 0)
{
while (m_IIName != objArrayName1[i] && i < 6) // Looking through the object name array to see if we have found an interactive object belonging in Phase A
{
i++;
}
if (i < 6) // The object belongs in Phase A
{ //If we have found an interractive item belonging in Phase A then we have to trigger it
Debug.Log("Found an inter item of phase A");
m_CurrentInteractible.transform.Rotate(Vector3.right * 10);
}
else // Did not belong in Phase A
{
i = 0;
}
}
else
{
while (m_IIName != objArrayName2[i] && i < 6) // Looking through the object name array to see if we have found an interactive object belonging in Phase B
{
i++;
}
if (i < 6) // The object belongs in Phase B
{ //If we have found an interractive item belonging in Phase B then we have to trigger it
Debug.Log("Found an inter item of phase B");
}
else
{
i = 0; // Did not belong in Phase B
}
}
}
//************************************************************************** I stoped coding here ********************************************************************
// 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(ray.origin, ray.direction);
}
if (ControllerIsConnected && m_LineRenderer != null)
{
m_LineRenderer.SetPosition(0, worldStartPoint);
m_LineRenderer.SetPosition(1, worldEndPoint);
}
}
public bool ControllerIsConnected
{
get
{
OVRInput.Controller controller = OVRInput.GetConnectedControllers() & (OVRInput.Controller.LTrackedRemote | OVRInput.Controller.RTrackedRemote);
return controller == OVRInput.Controller.LTrackedRemote || controller == OVRInput.Controller.RTrackedRemote;
}
}
public OVRInput.Controller Controller
{
get
{
OVRInput.Controller controller = OVRInput.GetConnectedControllers();
if ((controller & OVRInput.Controller.LTrackedRemote) == OVRInput.Controller.LTrackedRemote)
{
return OVRInput.Controller.LTrackedRemote;
}
else if ((controller & OVRInput.Controller.RTrackedRemote) == OVRInput.Controller.RTrackedRemote)
{
return OVRInput.Controller.RTrackedRemote;
}
return OVRInput.GetActiveController();
}
}
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();
}
}
}
答案 0 :(得分:0)
你是VRInteractiveItem订阅了动作OnOver,OnClick等。正在OnCancel中,这个动作被激活到GearVr上的后退按钮。
所以我建议你编写另一个类,比如(让我们假设激光给它的对象是一个CubeObject)对这个交互式对象有一个参考,并将这个类附加到对象上:
namespace VRStandardAssets.Menu
{
public class CubeObject : MonoBehaviour
{
[SerializeField] private VRInteractiveItem m_InteractiveItem; // The interactive item script reference from the same gameobject.
[SerializeField] private bool isLookingAtIt = false; //flag to know if player is onOver the object
private void OnEnable ()
{
m_InteractiveItem.OnOver += HandleOver;
m_InteractiveItem.OnOut += HandleOut;
m_InteractiveItem.OnCancel += HandleCancel;
}
private void OnDisable ()
{
m_InteractiveItem.OnOver -= HandleOver;
m_InteractiveItem.OnOut -= HandleOut;
m_InteractiveItem.OnCancel -= HandleCancel;
}
private void HandleCancel()
{
//Do stuff when I click on the object
doBackButtonStuff();
}
private void doBackButtonStuff(){
if(isLookingAtIt){
print("user has clicked back button while raycast hit it");
}
}
private void HandleOver()
{
//Do things when the object is onOver
isLookingAtIt = true;
}
private void HandleOut()
{
//Do things when the object is onOut
isLookingAtIt = false;
}
}
}