Supporting Bluetooth Devices in Unity

I recently started learning how to develop games in Unity.  After going through a couple of tutorials to familiarise myself with the tool I started work on integrating the Bluetooth sensors I have into my Unity projects. As Unity supports a C# based scripting language I thought it would be a relatively straightforward task to migrate my existing C# code from my Visual Studio projects. As probably to be expected migrating the code wasn’t as easy as I’d thought it be.

Unity supports C# through Mono which is an open-source version of Microsoft’s .NET platform. Unfortunately Mono does not support every feature you’d expect to find in the SerialPort class, specifically: –

  1. You can’t preview how many bytes you’ve received from your Bluetooth device via the BytesToRead property.
  2.  You can’t use the DataReceived event to process incoming data from your Bluetooth device.

Although these features are not supported, Mono will still compile your C# script successfully if you use them; they just won’t work during run-time e.g. DataReceived event is never triggered. The read data methods for the SerialPort class, such as ReadLine(..), do work as expected but you can’t simply call them during the main program loop (e.g. in an Update() call). The read data methods will block the main program loop until either they (1) read the desired amount of data or (2) time out.  For an interactive system, such as a videogame, you don’t want to be waiting for your Bluetooth device to send you something before you can do anything in the game e.g. render a frame. You’ll just end up with an inconsistent frame-rate if you do.

If you process incoming data in a thread independent of the main program loop you avoid this problem. If you also set the time-out period for the read data methods to something small you can also continually test whether sufficient data has been received from the Bluetooth device and not have to worry about not being able to close the thread when the game is closed (remember once called read data methods block until data is received).

Below is an example C# script I wrote which demonstrates this method, feel free to use this script to integrate your own Bluetooth devices into Unity. If you have any queries please give me a shout in the comments section.

UPDATE: In order to use the example you need to set your Unity project to use .NET 2.0 rather than the subset which is set by default. In your Unity project go to Edit – Project Settings – Player, select the “Settings for PC, Mac and Linux Standalone” tab and set the “API Optimization Level” to .NET 2.0. If you run the example as is Unity will throw an error that it can’t find the System.IO namespace.

using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.IO.Ports;
using System.Threading;
public class BTScript : MonoBehaviour {
private SerialPort serialPort = null;
String portName = "COM1"; // ** Example BT device specs **
int baudRate = 115200;
int readTimeOut = 100;
int bufferSize = 32; // Device sends 32 bytes per packet
bool programActive = true;
Thread thread;
/// <summary>
/// Setup the virtual port connection for the BT device at program start.
/// </summary>
void Start () {
try
{
serialPort = new SerialPort();
serialPort.PortName = portName;
serialPort.BaudRate = baudRate;
serialPort.ReadTimeout = readTimeOut;
serialPort.Open();
}
catch (Exception e) {
Debug.Log (e.Message);
}
// Execute a thread to manage the incoming BT data
thread = new Thread(new ThreadStart(ProcessData));
thread.Start();
}
/// <summary>
/// Processes the incoming BT data on the virtual serial port.
/// </summary>
void ProcessData(){
Byte[] buffer = new Byte[bufferSize];
int bytesRead = 0;
Debug.Log ("Thread started");
while (programActive) {
try {
// Attempt to read data from the BT device
// - will throw an exception if no data is received within the timeout period
bytesRead = serialPort.Read (buffer, 0, bufferSize);
// Use the appropriate SerialPort read method for your BT device e.g. ReadLine(..) for newline terminated packets
if(bytesRead > 0){
// Do something with the data in the buffer
}
}
catch (TimeoutException) {
// Do nothing, the loop will be reset
}
}
Debug.Log ("Thread stopped");
}
/// <summary>
/// Update this instance.
/// </summary>
void Update () {
}
/// <summary>
/// On program exit.
/// </summary>
public void OnDisable(){
programActive = false;
if (serialPort != null && serialPort.IsOpen)
serialPort.Close ();
}
}

16 thoughts on “Supporting Bluetooth Devices in Unity”

  1. Hi Kiel
    I was reading your post and I was wondering if it can help me to read and display data from bike speed & cadence sensors? by using this code, will the BT data be stored in bytesRead? I am very new to this…

    1. Hi Gleb,
      It depends on the type of Bluetooth device you have.
      The above code will only work for Classic Bluetooth. If your bike sensor is newer, say, made after 2011 , then it maybe a Bluetooth Low Energy device which has a completely different communication paradigm.
      If your sensor supports Classic Bluetooth then all received data will be read into the array variable “buffer”. The “bytesReceived” variable will tell you how much data you’ve received from the sensor.
      The example above is designed to process data as it becomes available i.e. when one or more bytes of data are received. You will need to configure the code for your particular sensor. Some sensors prefer to send data in a fixed sized packet e.g. 50 bytes of data every second. Other sensors prefer to send variable length sized packets e.g. a newline “\n” is used to indicate the end of a data sample. You need to identify how your sensor is formatting the data it passes you and write the necessary processing code. You can find out how you sensor formats its data by either consulting the sensor’s technical manual or from reverse engineering the device. The latter is obviously more difficult but it’s not impossible. You will also need to factor in Mono’s “SerialPort” limitations which I identified in my post.
      If your sensor is a Bluetooth LE device then the example will not work. I’ve only recently started learning to code for Bluetooth LE devices so I can’t help you on that note. There are Unity plugins that support Bluetooth LE but I’m not sure how well they work for Windows. Windows has terrible support for Bluetooth LE and I’ve seen quite a few instances of people capturing data from a phone and then pushing it over the Internet to a PC which is wonderfully insane.
      Anyways hope this helps, and good look with your project.
      – Kiel

      1. Thanks so much for the quick and elaborate response!!!
        So I can either get an older sensor or work a LE Bluetooth plug in… Is there one you can recommend that would work for my project? I am trying to read the speed&cadence data from the sensor into my Unity game. Doing it from the phone would not be an option I think as I only want to use a PC. Also how about implementing ANT+ protocols in Unity? I could not find much about it at all

        1. I’ve only just started learning how to work with Bluetooth LE and with Android to begin with, so I’m not much help on the Windows front.
          There is a sample project for LE heart monitors for Windows 8.1. But I’ve never managed to get it to read data off a device. Pairing sure, data reading nope. It also only works through the Metro interface which is annoying.
          If your looking to work with ANT+ protocols I suggest reading this. It contains a sample Visual Studio project, the C# code of which you may able to migrate to Unity.
          As to which bike sensor, I really can’t help you there as I haven’t owned one in decades. At a glance Polar offer a range of LE devices, code samples can be found here, and ANT has a searchable product directory.
          Hope this helps.
          – Kiel

  2. please can you help i have data from bluetooth, this data are of a accelerometer and with it i want to move a cube in unity, the system consist in the game for android y move the cube from bluetooth , how can i make it ? pleaseeee help me pleasee

    1. Hi Fabiloa,
      I’m afraid I don’t have time to give you any specific advice for your problem. The above code will work in Unity for any Classic Bluetooth device. You’ll just need to modify the receiver code to match the format your sensor transmits data in (see earlier comments concerning this topic). The code will not work for Bluetooth LE devices nor do I have any operational code for this. If I recall you can purchase the relevant code from the Unity asset store.
      What I would suggest is before integrating your sensor into Unity is to get a working command line program written in Java or C# using either Eclipse or Visual Studio and have it connect to and poll you sensor. There are many working examples for Bluetooth devices on the net written in these languages. Once you can successfully connect to your device using your test program you can look towards migrating it to Unity which while doable, given both Java and C# are supported by Unity, may require some tweaking given Unity doesn’t fully support the language instruction sets. If you read my post above you’ll see how I’ve had to adapt my C# code for Unity’s version of Mono.
      Hope this helps,
      – Kiel

  3. Hi Kiel,
    Thanks for this post and your blog in general – great stuff! I have been searching for a way to connect a Bluetooth LE heart rate sensor to my Unity project which will be built for standalone pc. There are many resources about connecting BLE through unity for mobile builds, but I have come up dry for how to connect and read the data for a pc build. Have you revisited this at all or know of any new resources to help accomplish this?
    Thanks,
    Jacob

    1. Thanks Jacob. Sadly not yet, it’s low priority at the moment as I’ve ton of other work to do. My spare time is largely focused on getting old biosensor tech to work at the moment and reviewing how they function (e.g. skin conductance sensors for an Apple II videogame :)).
      When I do get BLE to work I’ll upload the details. It’s clearly possible as I’ve seen more than a few apps that do it but nothing provided with source code.

      1. Hi Kiel,
        Thanks for the information. Do you have any update about BLE? I am looking for something very similar to what Jacob was trying to do with Heart Rates and couldnt find much information or tutorial online.
        After some struggle, I have managed to run the Bluetooth Generic Attribute Profile – Heart Rate Service (sample project from Microsoft) with successfully reading the Heart Rate data but couldnt bring it to Unity as it is using bunch of dll’s especially Windows Devices dll’s that are not available to Unity.
        Thanks!

        1. Hi,
          Sorry, no. I started some code but then got busy with work. You could try creating a wrapper that calls your BLE code from Unity. Been a very long time since I’ve done something like that, but off the top of my head you could write your own DLL for Unity to call and stuff the BLE code inside or you could create a network connection between Unity and the app your using for BLE. I’ve seen the latter approach in a Steam game that had a working BLE driver.
          – Kiel

  4. Hello Kiel, thanks for the information. Please tell me, the name of the serial port should be exactly “COM1”? Can I change this to a different name? What does it depend on?

  5. The COM port should be set to whatever your OS is detecting the virtual connection as. When you pair your BT device to your computer it should display what port it’s been attached to.
    If it doesn’t, and if your using Windows, you can go to the Devices and Printers and inspect which port it was bound to. Right click the relevant BT device, select Properties and go to Hardware. The port should be listed there.

  6. Hi Kiel, is it possible to make a Bluetooth connection with the HC-05 module? What I want is for Unity to send a Char data to the HC-05 but I still do not know how to implement it

    1. Hi,
      I’ve not used a HC-05 module before, presumably you have some code that dumps info from the chip onto the serial port. You should be able to see this using the Ardunio IDE serial monitor. If so, this code should work. You’ll need to modify the read function to whatever the HC-05 is spitting out though.
      – Kiel

  7. Hi, I’m just new to this and I was trying to have an android device to send a string or a message to another android device using bluetooth and an app. How would I need to change this code to make it work like that? Thanks in advance!!!

    1. This code is for a Unity client running on a PC using classic Bluetooth. It’s connecting via the virtual serial ports classic Bluetooth devices are configured to use. Can’t say for sure, but this code base is not appropriate for an Android deployment. You need to look up Android specific tutorials.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.