New To The Forum? Click Here To Read The How To Guide. -- Developers Click Here.

Does the Unity Editor support the Gear VR Controller? If not, how best can it be emulated?

firagabirdfiragabird Posts: 37
Brain Burst
This is a workflow-related question. While I'm developing my Gear VR app in Unity, can I use the VR controller directly within the editor on my PC when running? This would be much more convenient and speed up iteration time than having to constantly build the APK, install onto the phone, and test it there whenever I want to test some interaction-related changes.

In case this isn't possible, what's the next best solution to reducing my development iteration time when using the controller? Is it possible to emulate it by pairing the phone to the PC, kind of like how Daydream's motion controller emulator works? Or should I just emulate both head and hand orientation with keyboard WASD keys and the mouse, respectively?
S7 Exynos Nougat. 2015 & 2017 Gear VR.

Comments

  • imperativityimperativity Posts: 1,597 Oculus Staff
    @firagabird

    There are plans for this to be enabled in the future (no ETA).

    At present the gear controller will not work when paired with your PC.
  • firagabirdfiragabird Posts: 37
    Brain Burst
    @imperativity

    Thanks for the info. So in your opinion, what would be a good way to prototype a game that uses the Gear VR controller?
    S7 Exynos Nougat. 2015 & 2017 Gear VR.
  • imperativityimperativity Posts: 1,597 Oculus Staff
    @firagabird

    I'm looking into this right now and will update this thread if I can find anything to quicken this development process for you.


  • imperativityimperativity Posts: 1,597 Oculus Staff
    @firagabird

    I touched basis with the mobile team and their recommendation is to use a Touch controller but remove position tracking from the inputs reported.

    As described by the team, this isn't necessarily a perfect solution--as you won't get an analog for the arm model, and you don't get a touch pad--but it's a much faster way to iterate than pushing to the device every time.

    I'm looking into getting this approach formally typed up and documented in the near future.

  • firagabirdfiragabird Posts: 37
    Brain Burst
    edited July 27
    @imperativity

    This approach would have been the perfect compromise if Oculus made it possible for me to buy Rift in my country (the Philippines). :) I'm at least glad that developers more fortunate than me have this option for faster mobile VR development iteration.

    Please keep me posted on the VR controller support on PC status. In the meantime, I'll try to figure something out with just my PC and Gear VR, at least until Rift starts shipping in my country.
    S7 Exynos Nougat. 2015 & 2017 Gear VR.
  • greggtwep16greggtwep16 Posts: 3
    NerveGear
    The main purpose of my asset is high level controls without coding, but it does provide keyboard/mouse emulation of the gear vr controller in editor. Ctrl drag for the gear vr controller, alt drag for the headset, and various keys for the buttons/touchpad.

    https://www.assetstore.unity3d.com/en/#!/content/88829
  • MarkHenryCMarkHenryC Posts: 10
    NerveGear
    edited September 5
    After doing a search and finding this thread I decided to knock up a little script to read the controller in the Unity editor by passing it from the device via UDP. Drop the script in the scene, adding a pointer visual. Create an apk & send to Android. It's easily extendible. I can provide a demo project if anyone wants where I use the supplied Oculus Gear VR Controller model & added a simple pointer beam. (Is this the right place to stick code? The forum won't allow attachments.)
    // Read your Gear VR Controller in the Unity Editor
    // This script handles sending sending and receiving.
    // In the editor it receives and on Android it sends.
    // Use a GameObject for the pointer. There's a decent
    // model in the OVR Meshes folder. There's no need
    // for OVRManager to be in the scene, but if it is
    // there's no need for the OVRImput.Update() call.
    // Create your APK in the usual way and set your 
    // device to Developer Mode.
    // Prop it in front of you so it lines up with your
    // editor screen (a Cardboard headset is handy here).
    // The orientation is important for the pointer
    // to be interpreted correctly. You can of course
    // have it flat but you'll need to do some transforms to
    // the controller's output. This is just an example
    // and only shows the pointer position and direction.
    // You can easily add click status data to the string.
    // Before starting the app, make sure the orientation
    // is how you want it (see Start()), or alternatively add a button
    // and call InputTracking.Recenter() when you have
    // the device in position. Normally this would 
    // correspond with your PC's game view screen.
    //
    // Free for development use.
    // Mark H Carolan
    // http://quitesensible.com
    // mark@quitesensible.com
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Net;
    using System.Net.Sockets;
    using System.Net.NetworkInformation;
    using System.Text;
    using System.Linq;
    using System;
    using UnityEngine.VR;
    
    public class ControllerData : MonoBehaviour
    {
        public GameObject pointer;
    
        // These are arbitrary. Choose your favourite
        // port and set desired transmit resolution.
        // Here it's about 30fps.
    
        private const int port = 11000;
        private const float interval = 0.033f;
    
        private const string PREFIX_CONTROLLER = "GC";
        private const string PREFIX_ERROR = "ER";
    
        private string ourId;
        private float accum;
        private UdpClient broadcaster;
        private UdpClient listener;
        private int dummyCounter;
        private IPEndPoint endPoint;
        private bool received;
    
        void Awake()
        {
            ourId = SystemInfo.deviceModel.Substring(0, 3);
        }
    
        void Start()
        {
            broadcaster = new UdpClient();
            endPoint = new IPEndPoint(IPAddress.Broadcast, port);
    
            listener = new UdpClient(new IPEndPoint(IPAddress.Any, port));
            listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    
            accum = 0f;
            dummyCounter = 0;
        }
    
    
        void Update()
        {
            // RECEIVER MODE NOTE:
            // In Unity 5.6 and 2017 editor, we need to prime
            // the incoming buffer (or something like that) by
            // sending out a broadcast, even if we're just receiving.
            // In Unity 5.5 there's no need. Once we're getting 
            // data we can switch the broadcast off.
    
            bool sendData = (Application.platform == RuntimePlatform.Android) ||
                (Application.isEditor && !received);
    
            if (sendData)
            {
                accum += Time.deltaTime;
                if (accum >= interval)
                {
                    SendData();
                    accum = 0f;
                }
            }
    
            if (Application.isEditor)
            {
                if (listener.Available > 0)
                {
                    received = true;
    
                    IPEndPoint senderEp = null;
                    byte[] data = listener.Receive(ref senderEp);
    
                    string str = Encoding.Unicode.GetString(data);
                    if (!str.StartsWith(ourId)) // don't handle our own messages
                        ProcessData(str);
                }
            }
        }
    
        // Send controller data if Android or send dummy data
        // to activate receiver if Unity editor 5.6 or 2017
        private void SendData()
        {
            string data = null;
            if (Application.isEditor)
                data = (ourId + ++dummyCounter).ToString();
            else
            {
                OVRInput.Update();
                OVRInput.Controller activeController = OVRInput.GetActiveController();
    
                if (activeController == OVRInput.Controller.LTrackedRemote ||
                    activeController == OVRInput.Controller.RTrackedRemote)
                {
                    Quaternion rot = OVRInput.GetLocalControllerRotation(activeController);
                    Vector3 pos = OVRInput.GetLocalControllerPosition(activeController);
    
                    pointer.transform.position = pos;
                    pointer.transform.rotation = rot;
    
                    data = string.Format(PREFIX_CONTROLLER + ":{0}:{1}:{2}:{3}:{4}:{5}:{6}", 
                        pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, rot.w);
                }
                else
                    data = PREFIX_ERROR + ":ActiveController: " + activeController.ToString();
            }
    
            Byte[] buffer = Encoding.Unicode.GetBytes(data);
            broadcaster.Send(buffer, buffer.Length, endPoint);
        }
    
        // Read data and set pointer visual cue
        private void ProcessData(string strData)
        {
            if (!string.IsNullOrEmpty(strData))
            {
                string[] subs = strData.Split(':');
                int len = subs.Length;
                if (len > 0)
                {
                    var src = subs[0];
                    if (src == PREFIX_CONTROLLER)
                    {
                        if (len >= 8)
                        {
                            var px = (float)Convert.ToDouble(subs[1]);
                            var py = (float)Convert.ToDouble(subs[2]);
                            var pz = (float)Convert.ToDouble(subs[3]);
                            var qx = (float)Convert.ToDouble(subs[4]);
                            var qy = (float)Convert.ToDouble(subs[5]);
                            var qz = (float)Convert.ToDouble(subs[6]);
                            var qw = (float)Convert.ToDouble(subs[7]);
    
                            Quaternion rot = new Quaternion(qx, qy, qz, qw);
                            Vector3 pos = new Vector3(px, py, pz);
    
                            // This is what we're here for.
                            pointer.transform.position = pos;
                            pointer.transform.rotation = rot;
    
                        }
                    }
                    else if (src == PREFIX_ERROR && len > 1)
                    {
                        Debug.Log("Error from controller: " + subs[1]);
                    }
                }
            }
        }
    }
    



  • imperativityimperativity Posts: 1,597 Oculus Staff
    @MarkHenryC

    Thanks for this! We will be publishing a tech blog on the developer center with a complete walk-through on using a touch controller to emulate the gear VR controller. There will be code, samples and a unity project walk-through as well.
  • MarkHenryCMarkHenryC Posts: 10
    NerveGear
    It would be very handy if the Oculus Controller reading libs could built into a regular Android app. Would make it much simpler (in that there's no need for sig files and switching the phone to developer mode) for relaying data to a desktop environment.
  • ruud3DVruud3DV Posts: 7
    NerveGear
    Great solution MarkHenryC, thanks for sharing! Could you share the demo projectfile too?
  • MarkHenryCMarkHenryC Posts: 10
    NerveGear
    I have a small repo which I've just made public.
    Hope it's useful. I find it quite handy for developing Controller interactions in Unity Editor.
  • MarkHenryCMarkHenryC Posts: 10
    NerveGear
    A note on that: it does not work well in > Unity 5.5. UDP sockets seem flakey (or at least different enough to break existing code) in 5.6 and 2017.x. There is also some odd behaviour in the Oculus Controller read library: in 2017.2, sweeping the controller and hitting a button often results in the call OVRInput.GetActiveController() returning GamePad rather than OVRInput.Controller.LTrackedRemote or OVRInput.Controller.RTrackedRemote. Clicking a button again resets it. This never happens in Unity 5.5.
Sign In or Register to comment.