【Arduino】Unityを再生・停止させる物理ボタンを作ってみた

#はじめに
Oculus RiftとかViveをかぶっているとUnityを再生するのがとてもつらいですね。画面見えないし、キーボードも見えないのでCtrl + Pしづらい。
そんなとき、物理ボタンを押してUnityの再生ができれば便利なのではないかと思ってUnityを再生させる物理ボタンを作ってみました。

![IMG_1039 - ペイント 2016-07-06 14.22.41.png](https://qiita-image-store.s3.amazonaws.com/0/44288/981c3998-40f7-3fd0-14d5-23dfe473a5ec.png)

#環境
この記事では**Visual Studio 2015 Community**を使います。
UnityのバージョンはUnity5.3.5f1
OSは Windows 10です。

# ボタンを押してからUnityエディタを再生させるまでの流れ
物理ボタンの入力をArduinoで検出してデータ送信 
->　データを受信したWindowsアプリ側で Ctrl + P キーストロークを発行
　->　Unityエディタが再生される( エディタ再生のショートカットキーがCtrl + Pなので)

#1. 用意するもの
フットスイッチ　プラスチック赤
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/84d356b2-b956-2c5d-1542-5466cbc392a1.png" width = 180>
筆者は秋葉原のヒロセテクニカルで購入しました。 <a href = "https://www.google.co.jp/maps/place/%E3%83%92%E3%83%AD%E3%82%BB%E3%83%86%E3%82%AF%E3%83%8B%E3%82%AB%E3%83%AB%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/@35.6992415,139.768508,17z/data=!3m1!4b1!4m5!3m4!1s0x60188c1d07474f85:0x2a8ec27ddaf4227c!8m2!3d35.6992415!4d139.7706967"> Googleマップ </a>

<br>

Arduino Uno
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/0a70b9d1-58bd-ff59-6655-9e6758331f3d.png" width = 200>

<br>
わにぐちクリップ　(スイッチとArduinoの接続用)
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/555785eb-fc15-6f42-6730-69c166e09c06.png" width = 200>

<br>
ジャンプワイヤ　(スイッチとArduinoの接続用)
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/b6174357-7b89-a07d-5a80-72e044c838e4.png" width = 200>


#2. Arduino側の準備

##スケッチ
以下のようなスケッチをArduinoに書き込んでやります。

```
const int buttonPin = 12;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  int buttonState = digitalRead(buttonPin);
  if (buttonState == LOW) {
    Serial.println("Enter!!");
    delay(200);
  }
}
```
スケッチはこちらの記事(http://qiita.com/ie4/items/7c6764469f3d41c93a19) からお借りしました (ほぼパクリ)

## 配線
以下の図のようにデジタルピンの12番、GNDとボタンをつなぎます。
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/6955a4c3-ebd8-3c99-88d4-f7c30ce89c58.png">
↑ かなり雑な回路図

マイコンボードに書きめばArduino側の準備は完了です。

## 動作確認
PC側に移る前に動作確認をしておきましょう。

まず、メニュー -> シリアルモニタをクリックして シリアルモニタを開きます。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/29a250b4-8a9b-a5ab-b044-edb667e99fcf.png)

ボタンを押して Enter!! が出てくればOKです。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/d2444bce-4045-21e2-bcc3-49e1a487f2ce.png)

次にPC側のアプリケーションを作っていきます。


#3. PC側の準備

## 新規プロジェクトの作成
Visual C# -> Windows Form Applicationを選択。　プロジェクト名を UnityPlayButton　にしてOKをクリック。
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/30a209ea-e5ba-db37-7a3c-0aebe81655c5.png">
<br>
OKをクリックすると以下のようなWindowsフォームデザイナが開かれます。
<img src = "https://qiita-image-store.s3.amazonaws.com/0/44288/2aec1513-1062-fb3f-e145-a76b40c8bd2e.png" height = 400>

このフォームを編集してアプリケーションを作っていきます。

## フォームの作成
まず、ComboBoxをドラッグ＆ドロップしてフォームへ配置します.
![UnityPlayButton - Microsoft Visual Studio 2016-07-06 12.56.24.png](https://qiita-image-store.s3.amazonaws.com/0/44288/4d22cd1e-48fb-e809-8b82-3502947a5e5e.png)

ComboBoxをダブルクリックします。
![UnityPlayButton - Microsoft Visual Studio 2016-07-06 12.58.26.png](https://qiita-image-store.s3.amazonaws.com/0/44288/43a07f56-9cfb-7255-fe3a-a3061fd3b401.png)

コードが追加されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/75437445-8132-fe61-4f13-25ba893e7f26.png)

Shift + F7 を押してWindowsフォームデザイナーへ戻ります。

SerialPortをドラッグ＆ドロップしてフォームへ配置します
![UnityPlayButton - Microsoft Visual Studio 2016-07-06 13.04.51.png](https://qiita-image-store.s3.amazonaws.com/0/44288/9cfe7274-6734-e8ae-a8e9-fd3f9c660616.png)

<br>

Propertiesウィンドウの稲妻マークをクリック。
![UnityPlayButton - Microsoft Visual Studio 2016-07-06 13.09.48.png](https://qiita-image-store.s3.amazonaws.com/0/44288/761e22cf-39af-8097-553f-27b524fe0dcf.png)

<br>

DataReceived をダブルクリック
![UnityPlayButton - Microsoft Visual Studio 2016-07-06 13.08.28.png](https://qiita-image-store.s3.amazonaws.com/0/44288/61ac03d1-11a6-0b84-3bf5-9286796460a7.png)

コードが追加されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/52bf3af3-3f88-246e-830b-6a89c72ffc7a.png)
以上でフォームの編集は終わりです。　次にコードを書いていきます。

##ソースコード
まず、Form1.csを以下のように書き換えます。 

```Form1.cs
using System;
using System.Windows.Forms;
using System.IO.Ports;

namespace UnityPlayButton
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            string[] ports = SerialPort.GetPortNames();
            foreach (string port in ports)
            {
                comboBox1.Items.Add(port);
                Console.WriteLine(port);
                comboBox1.SelectedItem = port;
                serialPort1.Close();
                serialPort1.PortName = port;
                serialPort1.Open();
            }
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                string data = serialPort1.ReadLine();
                if (!string.IsNullOrEmpty(data))
                {
                    if (ActiveWindow.GetActiveWindowName() == "Unity")
                    {
                        // Unityのウィンドウを選択していたらCtrl + P する
                        SendKeys.SendWait("^p");
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            serialPort1.Close();
            string port = (String)comboBox1.SelectedItem;
            Console.WriteLine(port);
            serialPort1.PortName = port;
            serialPort1.Open();
        }
    }
}

```

次に以下のようなActiveWindow.csを作成します。 現在フォーカスが乗っている(アクティブになっている)ウィンドウの名前を
取得するクラスです。 名前はテキトーです(いい名前が思いつかなかった)

``` ActiveWindow.cs
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace UnityPlayButton
{
    class ActiveWindow
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();
        [DllImport("user32.dll")]
        public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

        // 現在アクティブになっているウィンドウの名前を取得
        public static string GetActiveWindowName()
        {
            int id;
            IntPtr hWnd = GetForegroundWindow();
            GetWindowThreadProcessId(hWnd, out id);
            return Process.GetProcessById(id).ProcessName;
        }
    }
}
```

以上でコードの編集は終わりとなります。　実際に動かしてみましょう。

#動かしてみる
Startボタンをクリックするとアプリケーションが起動します.
![「Unityを再生・停止させる押せる物理ボタンを作ってみた」を編集 - Qiita - Google Chrome 2016-07-06 13.32.12.png](https://qiita-image-store.s3.amazonaws.com/0/44288/b6949082-6407-ac4b-78c8-45253c78256c.png)

<br>

以下のようなウィンドウが出てくればOKです。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/63313509-aec8-870a-f595-415607d92258.png)

そしてこのアプリケーションを動かした状態のまま、Unityへ移ります。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/7baa5e3e-25b3-dd48-5d76-4c2d46ab7cf6.png)
↑Unityエディタ。

物理ボタンを押すとエディタが再生されます(完)

#参考URL
Arduinoで物理ボタンを作る (目立つボタンで「ッターーン！」しよう
http://qiita.com/ie4/items/7c6764469f3d41c93a19