まゆたまガジェット開発逆引き辞典

電子工作やプログラミングのHowtoを逆引き形式で掲載しています。作りたいモノを決めて学んでいくスタイル。プログラマではないので、コードの汚さはお許しを。参照していないものに関しては、コピペ改変まったく問いません

M5StackをArduinoのように使ってUnityに送る(MESHの動きタグ・アセットなし)

アナログ出力はちょっと工夫が必要っぽいので、まずはデジタル出力から。
Arduino使えば早いというツッコミはナシの方向で・・・(汗

ソニーMESHの動きタグを振ると、Unityのオブジェクトが移動します。
追記でたくさん振ると大きく動くようにすることで、アナログ出力っぽい挙動を出してみました。

テストなので簡単なものを。
上手くやれば、動きタグを振ってる間、キャラクターが走るということも可能です。
(キーボードで移動させるスクリプトに手を加えるだけ)

f:id:prince9:20180927032837j:plain

M5Stack(Arduino)とUnityとの接続は前回と同じです。アセットは使いません。
prince9.hatenablog.com

Arduinoでシリアルモニタを立ち上げた状態でUnityを動かすと、シリアルが認識しません。注意!

■準備
ソニーMESHの「動きタグ」
ソニーMESHの「GPIO」
・M5Stack(Arduino)
・ワイヤー

●MESH
これを下記のように接続します。
f:id:prince9:20180925205928p:plain

●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のままになってしまいます。
動くタグの動作確認のために音も鳴らしています。
f:id:prince9:20180927030917p:plain

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;

		}

		
	}
}