Forum Discussion
firagabird
8 years agoAdventurer
Does the Unity Editor support the Gear VR Controller? If not, how best can it be emulated?
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 ...
MarkHenryC
8 years agoProtege
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]);
}
}
}
}
}
Quick Links
- Horizon Developer Support
- Quest User Forums
- Troubleshooting Forum for problems with a game or app
- Quest Support for problems with your device
Other Meta Support
Related Content
- 2 months ago