Does the Unity Editor support the Gear VR Controller? If not, how best can it be emulated? — Oculus
Welcome to the Oculus Developer Forums!

Your participation on the forum is subject to the Oculus Code of Conduct.

In general, please be respectful and kind. If you violate the Oculus Code of Conduct, your access to the developer forums may be revoked at the discretion of Oculus staff.

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

firagabirdfiragabird Posts: 155
Art3mis
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. 2017 Gear VR. Public test channel.

Comments

  • firagabirdfiragabird Posts: 155
    Art3mis
    @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. 2017 Gear VR. Public test channel.
  • firagabirdfiragabird Posts: 155
    Art3mis
    edited July 2017
    @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. 2017 Gear VR. Public test channel.
  • 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: 33 Oculus Start Member
    edited September 2017
    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]);
                    }
                }
            }
        }
    }
    



  • MarkHenryCMarkHenryC Posts: 33 Oculus Start Member
    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: 17 Oculus Start Member
    Great solution MarkHenryC, thanks for sharing! Could you share the demo projectfile too?
  • MarkHenryCMarkHenryC Posts: 33 Oculus Start Member
    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: 33 Oculus Start Member
    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.
  • MarkHenryCMarkHenryC Posts: 33 Oculus Start Member
    edited December 2017
    I've pulled the plug on this one. Unity > 5.54 doesn't seem to be accepting incoming UDP data in the editor, which is necessary for this to work. So it's not a general solution. Bug is reported and acknowledged by Unity (948027) but is not currently being progressed. I imagine it's extremely low priority due to the tiny number of users it affects. Using the Rift touch controller is a pretty decent substitute when developing for Gear VR.
  • firagabirdfiragabird Posts: 155
    Art3mis
    @MarkHenryC

    It's actually the better solution, and is officially recommended by Oculus as shown by their posted guide. Unfortunately, it's still a solution that can't be implemented in any of the countries not part of Oculus' 20 supported ones, including my own.

    For the purposes of faster iterations during development, the recommended method for those with only a Gear VR is to compile the build faster using the "build only scripts" option in the build settings. I haven't tried it yet, though.
    S7 Exynos Nougat. 2017 Gear VR. Public test channel.
Sign In or Register to comment.