Перемещение куба с помощью контроллера Gear VR в Unity

Я пытаюсь создать приложение Gear VR с контроллером Gear VR и Oculus SDK. Я получил GazePointerRing для работы с префабом контроллера. В моем приложении есть сетка, которую я могу перемещать с помощью контроллера Gear VR. Он обнаруживает кубики, которые я поместил в сцену. Сейчас я хочу навести сетку на куб и удерживать кнопку на контроллере, чтобы куб прилип к моей модели контроллера и мог перемещаться, пока я не отпущу кнопку. Я искал в сценарии OVR Physics Raycaster, как я могу вызвать попадание raycast и ввести его в команду кнопки в операторе if. Но я не могу найти способ вызвать попадание лучей с объектом. Это код Oculus в скрипте OVR Physics Raycaster:

using System.Collections.Generic;

namespace UnityEngine.EventSystems
{
    /// <summary>
    /// Simple event system using physics raycasts.
    /// </summary>
    [RequireComponent(typeof(OVRCameraRig))]
    public class OVRPhysicsRaycaster : BaseRaycaster
    {
        /// <summary>
        /// Const to use for clarity when no event mask is set
        /// </summary>
        protected const int kNoEventMaskSet = -1;


    /// <summary>
    /// Layer mask used to filter events. Always combined with the camera's culling mask if a camera is used.
    /// </summary>
    [SerializeField]
    public LayerMask m_EventMask = kNoEventMaskSet;

    protected OVRPhysicsRaycaster()
    { }

    public override Camera eventCamera
    {
        get
        {
            return GetComponent<OVRCameraRig>().leftEyeCamera;
        }
    }

    /// <summary>
    /// Depth used to determine the order of event processing.
    /// </summary>
    public virtual int depth
    {
        get { return (eventCamera != null) ? (int)eventCamera.depth : 0xFFFFFF; }
    }

    /// <summary>
    /// Event mask used to determine which objects will receive events.
    /// </summary>
    public int finalEventMask
    {
        get { return (eventCamera != null) ? eventCamera.cullingMask & m_EventMask : kNoEventMaskSet; }
    }

    /// <summary>
    /// Layer mask used to filter events. Always combined with the camera's culling mask if a camera is used.
    /// </summary>
    public LayerMask eventMask
    {
        get { return m_EventMask; }
        set { m_EventMask = value; }
    }


    /// <summary>
    /// Perform a raycast using the worldSpaceRay in eventData.
    /// </summary>
    /// <param name="eventData"></param>
    /// <param name="resultAppendList"></param>
    public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
    {
        // This function is closely based on PhysicsRaycaster.Raycast

        if (eventCamera == null)
            return;

        OVRRayPointerEventData rayPointerEventData = eventData as OVRRayPointerEventData;
        if (rayPointerEventData == null)
            return;

        var ray = rayPointerEventData.worldSpaceRay;

        float dist = eventCamera.farClipPlane - eventCamera.nearClipPlane;

        var hits = Physics.RaycastAll(ray, dist, finalEventMask);

        if (hits.Length > 1)
            System.Array.Sort(hits, (r1, r2) => r1.distance.CompareTo(r2.distance));

        if (hits.Length != 0)
        {
            for (int b = 0, bmax = hits.Length; b < bmax; ++b)
            {
                var result = new RaycastResult
                {
                    gameObject = hits[b].collider.gameObject,
                    module = this,
                    distance = hits[b].distance,
                    index = resultAppendList.Count,
                    worldPosition = hits[0].point,
                    worldNormal = hits[0].normal,
                };
                resultAppendList.Add(result);
            }
        }
    }

    /// <summary>
    ///  Perform a Spherecast using the worldSpaceRay in eventData.
    /// </summary>
    /// <param name="eventData"></param>
    /// <param name="resultAppendList"></param>
    /// <param name="radius">Radius of the sphere</param>
    public void Spherecast(PointerEventData eventData, List<RaycastResult> resultAppendList, float radius)
    {
        if (eventCamera == null)
            return;

        OVRRayPointerEventData rayPointerEventData = eventData as OVRRayPointerEventData;
        if (rayPointerEventData == null)
            return;

        var ray = rayPointerEventData.worldSpaceRay;

        float dist = eventCamera.farClipPlane - eventCamera.nearClipPlane;

        var hits = Physics.SphereCastAll(ray, radius, dist, finalEventMask);

        if (hits.Length > 1)
            System.Array.Sort(hits, (r1, r2) => r1.distance.CompareTo(r2.distance));

        if (hits.Length != 0)
        {
            for (int b = 0, bmax = hits.Length; b < bmax; ++b)
            {
                var result = new RaycastResult
                {
                    gameObject = hits[b].collider.gameObject,
                    module = this,
                    distance = hits[b].distance,
                    index = resultAppendList.Count,
                    worldPosition = hits[0].point,
                    worldNormal = hits[0].normal,
                };
                resultAppendList.Add(result);
            }
        }
    }
    /// <summary>
    /// Get screen position of this world position as seen by the event camera of this OVRPhysicsRaycaster
    /// </summary>
    /// <param name="worldPosition"></param>
    /// <returns></returns>
    public Vector2 GetScreenPos(Vector3 worldPosition)
    {
        // In future versions of Uinty RaycastResult will contain screenPosition so this will not be necessary
        return eventCamera.WorldToScreenPoint(worldPosition);
    }
}
}

person grunter-hokage    schedule 30.09.2017    source источник


Ответы (1)


Предварительное условие: убедитесь, что в вашей сцене есть диспетчер OVR, это синглтон и требуется для работы контроллера GearVR (класс OVRInput).

Мой обычный подход - направить луч из позиции привязки контроллера вперед и проверить, попадает ли он в желаемый объект.

public class SampleScript : MonoBehaviour
{
    public Transform anchorPos;
    public GameObject detectionLineObject; // a gameObject with a line renderer

    private RaycastHit _hitInfo;
    private LineRenderer _detectionLine;

    void Start()
    {
        GameObject line = Instantiate(detectionLineObject);
        _detectionLine = line.GetComponent<LineRenderer>();
    }

    void Update()
    {
        DetectionManager();
    }

    void DetectionManager()
    {
        // check if controller is actually connected
        if (!OVRInput.IsControllerConnected(OVRInput.Controller.RTrackedRemote) || !OVRInput.IsControllerConnected(OVRInput.Controller.LTrackedRemote))
        {
            return;
        }
        // launch a ray from the OVRCameraRig's Anchor Right
        if (Physics.Raycast(anchorPos.position, anchorPos.forward, out _hitInfo))
        {
            // set our line points
            _detectionLine.SetPosition(0, anchorPos.position);
            _detectionLine.SetPosition(1, _hitInfo.point);

            MyComponent target = _hitInfo.collider.gameObject.GetComponent<MyComponent>();

            if (target != null)
            {
                // Do you stuff here
                target.StartInteraction();
            }
        }
        else
        {

            // point our line to infinity
            _detectionLine.SetPosition(0, anchorPos.position);
            _detectionLine.SetPosition(1, anchorPos.forward * 500.0f);
        }
    }
}
person Omar Guendeli    schedule 30.09.2017
comment
У меня в сцене есть OVRManager. Спасибо, что поделились своим подходом Raycast, он выглядит таким понятным. Думаю, я могу работать над этим и постараюсь реализовать это сейчас. - person grunter-hokage; 01.10.2017
comment
Привет, еще раз несколько вопросов о вашем подходе к сценарию raycast. 1. Линия обнаружения игрового объекта - это контроллер, которым вы нацеливаетесь, или это игровой объект, с которым вы хотите взаимодействовать? 2. Какова цель кода: MyComponent target = _hitInfo.collider.gameObject.GetComponent ‹MyComponent› (); А каким должен быть MyComponent? Как, например, переместить куб в другое место, указав на него, каким должен быть MyComponent? - person grunter-hokage; 05.10.2017