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 ();
	}
}

6 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

Leave a Reply

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