简体   繁体   中英

Unity Gear Vr Object Interaction

I want to select an object in the scene with the Gear VR controller when the the laser has hit an object and the user presses the back side button of the controller. I have done the raycasting and the laser for the controller and it's working fine but I can not find a way to make the selection work. The code is as follows and I also have commented the part which I have written and what it's supposed to be doing.

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();

        }
    }
}

You're VRInteractiveItem is subscribed to the actions OnOver, OnClick, etc. Being OnCancel the action suscribed to the back button on GearVr.

So I recommend you to code another class like (let's suppouse that the object to which the laser gives it is a CubeObject) who have a refference to that Interactive Object, and attach this class to the object:

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;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM