ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【Unity/Arduino】UnityとArduinoを連携してみた

 明けましておめでとうござます。ブログのネタがないまま放置していたら気づいたら年が明けていました。

 久々の記事ですがタイトルにある通りUnityとArduinoを連携させてみました。

 具体的にはArduinoで取得した照度センサーの値をシリアルでUSBから送り、Unityの画面上に表示させるというものです。

 では説明していきます。


1:材料/開発環境
■開発環境

■素材


2:Arduino側の準備
 以下のようにArduino側の回路を組みます。
f:id:rikoubou:20180116164959p:plain

 Arduino Unoに以下のスケッチを書き込みます。

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  int v = analogRead(0);
  Serial.println(v);
  delay(1000);
}

 Aduino IDEのシリアルモニタを立ち上げて「115200bps」を選択すると
1秒ごとに照度センサーの値が表示されます。

 照度センサーのところを指で押し付けたり離したりすると値が変化します。


3:Unityで新しいプロジェクトを作成&ビルド設定
 Arduino側の準備ができたら次にUnityを立ち上げて新しいプロジェクトを作成します。

 新しいプロジェクトを作成したらFile→Build Settingsをクリックします。
f:id:rikoubou:20180116170258p:plain

 立ち上がった画面の下にあるPlayer Settingsボタンをクリックして
出てきたInspectorのOther Settingsにある「Api Compatibility Level」を
「.NET 2.0」に変更します。
f:id:rikoubou:20180116170525p:plain


4:空のGameObjectを作成しSerialHandlerスクリプトをアタッチする
 Hierarchyを右クリックし「Create Empty」を選択して空のGameObjectを追加します。
 その空のGameObjectの名前を「SerialHandler」に変更します。

 次にAssetsを右クリックし、Create→FolderでScriptフォルダを作成します。

 そのフォルダの中に入って再び右クリックし、Create→C#Scriptを選択して
「SerialHandler」の名前でスクリプトファイルを作成します。

 作成されたスクリプトファイルをダブルクリックして以下のようにソースを記述します。(ポート名のところは適宜変更してください)

using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System.Threading;

public class SerialHandler : MonoBehaviour
{
	public delegate void SerialDataReceivedEventHandler(string message);
	public event SerialDataReceivedEventHandler OnDataReceived;

	public string portName = "/dev/tty.usbmodem1421"; // ポート名(Macだと/dev/tty.usbmodem1421など)
	public int baudRate    = 115200;  // ボーレート(Arduinoに記述したものに合わせる)

	private SerialPort serialPort_;
	private Thread thread_;
	private bool isRunning_ = false;

	private string message_;
	private bool isNewMessageReceived_ = false;

	void Awake()
	{
		Open();
	}

	void Update()
	{
		if (isNewMessageReceived_) {
			OnDataReceived(message_);
		}
		isNewMessageReceived_ = false;
	}

	void OnDestroy()
	{
		Close();
	}

	private void Open()
	{
		serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
		//または
		//serialPort_ = new SerialPort(portName, baudRate);
		serialPort_.Open();

		isRunning_ = true;

		thread_ = new Thread(Read);
		thread_.Start();
	}

	private void Close()
	{
		isNewMessageReceived_ = false;
		isRunning_ = false;

		if (thread_ != null && thread_.IsAlive) {
			thread_.Join();
		}

		if (serialPort_ != null && serialPort_.IsOpen) {
			serialPort_.Close();
			serialPort_.Dispose();
		}
	}

	private void Read()
	{
		while (isRunning_ && serialPort_ != null && serialPort_.IsOpen) {
			try {
				message_ = serialPort_.ReadLine();
				isNewMessageReceived_ = true;
			} catch (System.Exception e) {
				Debug.LogWarning(e.Message);
			}
		}
	}

	public void Write(string message)
	{
		try {
			serialPort_.Write(message);
		} catch (System.Exception e) {
			Debug.LogWarning(e.Message);
		}
	}
}

 ソースの記述が終了したらSerialHandlerのスクリプトファイルを
SerialHandlerのオブジェクトにドラッグ&ドロップしてアタッチします。
f:id:rikoubou:20180116171948p:plain


5:Textを作成しSerialLightスクリプトをアタッチする
 Hierarchyを右クリックしUI→Textを選択してTextを追加します。
 追加したTextをクリックしInspectorのFontSizeや座標位置、表示範囲などを調整します。

 自分の設定値はこんな感じにしました。
f:id:rikoubou:20180116172840p:plain

 次にAssetsのScriptフォルダを右クリックし、Create→C#Scriptを選択して
「SerialLight」の名前でスクリプトファイルを作成します。
 作成されたスクリプトファイルをダブルクリックして以下のようにソースを記述します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SerialLight : MonoBehaviour {

	public SerialHandler serialHandler;
	public Text text;

	// Use this for initialization
	void Start () {
		//信号を受信したときに、そのメッセージの処理を行う
		serialHandler.OnDataReceived += OnDataReceived;
	}
	
	// Update is called once per frame
	void Update () {
		
	}

	/*
	 * シリアルを受け取った時の処理
	 */
	void OnDataReceived(string message) {
		try {
			text.text = message; // シリアルの値をテキストに表示
		} catch (System.Exception e) {
			Debug.LogWarning(e.Message);
		}
	}
}

 ソースの記述が終了したらSerialLightのスクリプトファイルを
Textのオブジェクトにドラッグ&ドロップしてアタッチします。
f:id:rikoubou:20180116173335p:plain

 次にアタッチしたTextオブジェクトをクリックしてInspectorを表示させます。
 SerialHandlerとTextのところの右にある○をクリックして
それぞれオブジェクトを対応させます。
f:id:rikoubou:20180116173700p:plain
f:id:rikoubou:20180116173708p:plain


6:Unityで実行する
 ArduinoとPCをUSBケーブルで接続した状態で作成したUnityのプロジェクトを実行します。
 すると以下のようにTextオブジェクト部分に照度センサーの値が表示されるようになります。
f:id:rikoubou:20180116174040p:plain

 センサー部分を指で押し付けたり離したりすると値が変動するのがわかると思います。


 以上がArduinoとUnityを連携してみた内容です。
 シリアルの値をUnity上で取得して反映できることがわかったので、色々なことに使えそうですね。


・追記
 以下の記事で今度は加速度センサと連携させてみました。
rikoubou.hatenablog.com


・参考資料