M5StackをArduinoのように使ってUnityに送る(MESHの動きタグ・アセットなし)
アナログ出力はちょっと工夫が必要っぽいので、まずはデジタル出力から。
Arduino使えば早いというツッコミはナシの方向で・・・(汗
ソニーMESHの動きタグを振ると、Unityのオブジェクトが移動します。
追記でたくさん振ると大きく動くようにすることで、アナログ出力っぽい挙動を出してみました。
テストなので簡単なものを。
上手くやれば、動きタグを振ってる間、キャラクターが走るということも可能です。
(キーボードで移動させるスクリプトに手を加えるだけ)
M5Stack(Arduino)とUnityとの接続は前回と同じです。アセットは使いません。
prince9.hatenablog.com
※Arduinoでシリアルモニタを立ち上げた状態でUnityを動かすと、シリアルが認識しません。注意!
■準備
・ソニーMESHの「動きタグ」
・ソニーMESHの「GPIO」
・M5Stack(Arduino)
・ワイヤー
●MESH
これを下記のように接続します。
●Unity側(アセットなし)
1.Unityのプロジェクトを作り、「GameOBject」メニュー→「3DObject」→「Cube」などを選び、適当にオブジェクトを作る
2.「File」メニュー→「Build Settings」を選択し、「Player Settings」をクリックする
3.Inspectorの「Other Settings」→「Api Compatibility Level」を「.NET 2.0」にする
4.「Build Settings」を閉じる
5.「Assets」を右クリックし、「Create」→「C# Script」を選択する
6.「MESHReceive」など適当にファイル名をつけて、後からスクリプトを書く
7.スクリプトを書いたら保存し、「Hierarchy」にある1.で作ったオブジェクト名にドラッグ&ドロップして適用する
■コード
まずMESHは以下になります。
動きタグで振動を認識したら、デジタル出力をHight(ON)にします。その1秒後にデジタル出力をLow(OFF)にすることで、Hight(ON)の状態をリセットしています。
リセットしないと、振った後にHightのままになってしまいます。
動くタグの動作確認のために音も鳴らしています。
●Arduino(M5Stack)コード
これも前のこちらのコードを改良したものです。
prince9.hatenablog.com
動きタグが振られたときが1、振られていないときは0をUnityに送っています。
M5Stackを使う利点として、簡単にシリアルモニタ代わりにできるという点があります。
UnityやProcessingなど、他の開発環境にデータを送る場合、Arduinoアプリのシリアルモニタが動いているとエラーが出るので・・・
#include <M5Stack.h> #define MESH_pin 36 // GPIOをGPIO36につなぐ int mdata = 0; //MESHのデータ用変数 int sdata = 0; //0or1に変換する変数 void setup(){ M5.begin(); Serial.begin(9600); pinMode(MESH_pin, INPUT); } void loop() { // 画面クリア M5.Lcd.clear(); M5.Lcd.setCursor(0, 0); mdata = analogRead(MESH_pin); //動きタグデータ読み込み sdata = mdata / 3000; //データが振られていないときは0、振ったときは3700〜3800前後で出てくるので、0か1かに変換 Serial.println(sdata); // シリアルに出力 //Unityにデータを送るとシリアルモニタが使えないので、M5Stackをシリアルモニタ代わりに M5.Lcd.setTextColor(WHITE); M5.Lcd.setTextSize(5); M5.Lcd.print(sdata); delay(500); M5.update(); }
●Unity
動きタグが繊細なせいか、一度振っても、下記のように複数値が返ってくることがあります。
0 ←振ってない
1 ←実際に振った
1 ←自分的には誤認識
1 ←自分的には誤認識
0 ←振ってない
なので、実際に振ったときのみ処理を行うよう、1の値を出した回数をカウントする変数「count」を作っています。
まずは単純に「振ったら動く」です。振るごとに動きます。
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO.Ports; public class meshUnityScript : MonoBehaviour { private int mMove = 0; private int count = 0; //new SerialPort("")にArduinoアプリで調べてメモしたシリアルポート名を指定する SerialPort sp = new SerialPort("/dev/cu.SLAB_USBtoUART", 9600); // Use this for initialization void Start () { if (!sp.IsOpen) { sp.Open(); sp.ReadTimeout = 1000; } else { sp.Close(); } } // Update is called once per frame void Update () { //文字列を数値に変換、meshMoveがArduinoアプリから送られてきた値 int meshMove = int.Parse(sp.ReadLine()); Debug.Log(meshMove); //動きタグを振ったとき(meshMoveが1のとき) if(meshMove > 0) { count += 1; } else { count = 0; } //動きタグを「実際に振ったとき」オブジェクトを動かす if(count == 1) { mMove += 1; transform.Translate(Vector3.left * mMove,Space.World); } } }
誤認識をあまり厳密に捉えず、「めっちゃ振ったらそのぶんだけ動く」=「めっちゃ振ったら大きく動く」場合のコードはこちらです。
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO.Ports; public class meshUnityScript : MonoBehaviour { private int mMove = 0; private int count = 0; //new SerialPort("")にArduinoアプリで調べてメモしたシリアルポート名を指定する SerialPort sp = new SerialPort("/dev/cu.SLAB_USBtoUART", 9600); // Use this for initialization void Start () { if (!sp.IsOpen) { sp.Open(); sp.ReadTimeout = 1000; } else { sp.Close(); } } // Update is called once per frame void Update () { //文字列を数値に変換、meshMoveがArduinoアプリから送られてきた値 int meshMove = int.Parse(sp.ReadLine()); Debug.Log(meshMove); //動きタグを振ったとき(meshMoveが1のとき) if(meshMove > 0) { count += 1; mMove += 1; transform.Translate(Vector3.left * mMove,Space.World); } else { count = 0; } } }