UnityではC#が使えるので、シリアル通信用のクラス(SerialPortクラス)を使うことが出来ます。ただ、Unity上でシリアル受信をすると速度がでないため、シリアル通信用のプラグインを作ります。
Arduinoでシリアル送信プログラムを作る
まずはテスト用にArduinoのプログラムを作ります。
シリアル通信で、アナログピンから得られた値を送信するプログラムです。
void setup() { Serial.begin(115200); } void loop() { int v = analogRead(0); Serial.println(v); }
setpu関数の中でSerialを使う準備をしています。
loop関数の中ではアナログポート0番の電圧値を取得し、それをシリアルで送信しています。
プラグインの作成
続けてシリアルを受信するためのプラグイン(DLL)を作成します。
ここで作成するDLLはUnityのプロジェクトフォルダに入れて使います。
Macの環境でもMonodevelopを使えばDLLを作ることが出来ます。
まずは/Application/Unity/Monodevelop.appを起動します。メニューバーから「File」→「New」→「Solution」を選択します。
プロジェクト設定画面でプロジェクト名を入力後「Create」ボタンを押します。ここでは「SerialLib」という名前にしました。
UnityのC#のバージョンに対応するため、フレームワークを.NET3.5に変更します。
メニューバーから「Project」→「SerialLib Option」を選択してウインドウを開き、左側のペインから「Build」→「General」→「Target framework」の項目を「.NET 3.5」に変更して下さい。
エディタに戻り、下記のシリアル通信の受信側のコードを記述して下さい。
Unity5の環境ではSerialPortクラスのRead関数を呼ぶとフリーズしてしまうため、ReadLine関数を使っています。
メニューバーから「Build」→「Build SerialLib」を選択してコンパイルして下さい。
プロジェクトフォルダの中の/bin/Debug/の中に「serialLib.dll」が作られます。
using System; using System.Threading; using System.IO.Ports; using System.Runtime.InteropServices; namespace SerialLib { public class UnitySerial { SerialPort serial; byte[] buf; string message; Thread SerialThread; bool isThreading = false; public UnitySerial(string portName, int baudRate, int bufSize) { buf = new byte[bufSize]; Init ( portName, baudRate ); SerialThread = new Thread (this.UpdateData); } public void ThreadStart() { SerialThread.Start (); } public void ThreadEnd() { isThreading = false; SerialThread.Abort (); serial.Close (); } void Init(string portName, int baudRate) { serial = new SerialPort (portName, baudRate, Parity.None, 8, StopBits.One); try { serial.Open(); serial.DtrEnable = true; serial.RtsEnable = true; serial.DiscardInBuffer(); serial.ReadTimeout = 5; } catch( Exception e ) { serial = null; return; } } public string GetData() { return message; } public void UpdateData() { isThreading = true; while (isThreading) { int read = 0; try { message = serial.ReadLine(); } catch(TimeoutException e) { } } } } }
Unityからプラグイン経由でデータを取得する
最後にUnityでシリアル通信のデータを受信する部分を作成しましょう。
まずはUnityでプロジェクトを作成し、Assetsフォルダの下にPluginsフォルダを作成します。
そのなかに先ほど作成した「SerialLib.dll」を入れて下さい。
続いてシリアルを受信するためのC#スクリプトを作成します。
プロジェクトビューで「Create」→「C# Script」を選択し「SerialTest」という名前で保存します。
このファイルに次のスクリプトを入力して下さい。
using UnityEngine; using System.Collections; using System.IO.Ports; using System.Runtime.InteropServices; public class SerialTest : MonoBehaviour { public GameObject rocket; public static SerialLib.UnitySerial serial; void Start() { serial = new SerialLib.UnitySerial ("/dev/cu.usbmodem1D1141", 115200, 256); serial.ThreadStart (); } void Update() { string str = serial.GetData (); if (str != null) { int r = int.Parse (str); } Debug.Log (serial.GetData ()); } void OnDestroy() { serial.ThreadEnd (); } }
UnitySerial のコンストラクタに渡している第一引数はポート名、第二引数は通信速度、第三引数は受信バッファのサイズです。
ポート名はArduinoのメニューバーから「ツール」→「シリアルポート」で調べることが出来ます。
Unityエディタに戻ると「The type or namespace name 'Ports' does not exist in the System.IO」というエラーが出ています。
これは、Unityがデフォルトで.Netのサブセットを使うようになっているのが原因です。
.Netのすべての機能が使えるように変更しましょう。
Unityのメニューバーから「Edit」→「Project Settings」→「Player」を選択します。
インスペクタから「Api Compatibility Level」の項目を「.NET 2.0」に設定して下さい。
作成したスクリプトを「Main Camera」にアタッチ(空のゲームオブジェクトを作って、それにアタッチでももちろんOKです)して動作確認してみてください。
ちゃんと動いていれば、UnityのコンソールにArduinoから送信されたデータが表示されるはずです。