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

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

MESHの動きタグでUnityちゃんを走らせる(アセットなし)

ソニーMESHの動きタグをめっちゃ振ると、Unityちゃんが走ります。
疲れるので、人によってはスクリプトの微調整が必要かもです。
とりあえずできたのでポストです。

GPIOを使い、M5Stack(Arduino)経由でUnityにデータを送ります。
f:id:prince9:20180927053705p:plain

基本的には下記と同じです。
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.アセットストアからUnityちゃんのデータをダウンロードする
6.アセットストアの「ダウンロードボタン」を押した後に「インポートボタン」を押す
7.「Import」をクリックし、「Heirarchy」にUnityちゃんをドラッグ&ドロップする
(「UnityChan」→「Models」→「unitychan」)

8.「Assets」を右クリックし、「Create」→「C# Script」を選択する
9.「MESHReceive」など適当にファイル名をつけて、後からスクリプトを書く
10.スクリプトを書いたら保存し、「Hierarchy」にあるUnityちゃんにドラッグ&ドロップして適用する

11.「Create」→「Animator Controller」を選択し「UnitychanMoveController」などに変更
12.「Assets」の中にある「UnitychanMoveController」をダブルクリックし、画面左上の「Animator」タブが選択されていることを確認
f:id:prince9:20180927050844p:plain
13.灰色の何もないところで右クリックし、「Create State」→「Empty」を選択
14.「New State」をクリックし、名前を「Idle」にする
15.もう一度灰色の何もないところで右クリックし、「Create State」→「Empty」を選択
16.名前を「Run」にする
17.「Idle」をクリックし、「Inspector」の「Motion」の横の◯アイコンをクリック
f:id:prince9:20180927050948p:plain
15.「WAIT00」をクリックして、モーションを設定する
16.「Run」をクリックし、「Inspector」の「Motion」の横の◯アイコンをクリック
17.「RUN00_F」をクリックして、モーションを設定する
18.「Idle」を右クリックし、「Make Transition」を選択する
19.白い矢印がのびるので、「Run」をクリックする。これはアニメーションが待機状態(Idle)から走る(run)に移行する設定を示している
f:id:prince9:20180927051833p:plain
20.白い矢印をクリックし、「Inspector」→「Has Exit Time」のチェックを外す。このチェックはアニメーションが終了するまで次のアニメーションが開始されないという設定で、もっさりとした動きになることがある
21.下記の「+」ボタンをクリックし、「Bool」を選ぶ
f:id:prince9:20180927051915p:plain
22.「New Bool」を「Running」と名前を変える
23.「Conditions」の「+」ボタンをクリックし、「Running」を「true」にする
f:id:prince9:20180927052034p:plain
24.「Run」を右クリックし、「Make Transition」を選択する
25.白い矢印がのびるので、「Idle」をクリックして下記のようにする
f:id:prince9:20180927052136p:plain
26.できた矢印をクリックし、「Inspector」→「Has Exit Time」のチェックを外す
27.「Conditions」の「+」ボタンをクリックし、「true」となっているところをクリックして「false」にする
f:id:prince9:20180927052212p:plain
28.「Hierarchy」のunitychanを選択し、「inspector」→「Animator」 →「Controller」の「None」と書かれているところに、「Assets」の中にある「UnitychanMoveController」をドラッグ&ドロップする
29.「Inspector」→「Animator」の「Apply Root Motion」のチェックを外す。プログラミングによってキャラクターを動かすときはこのチェックを外す


■コード
まずMESHは以下になります。
動きタグで振動を認識したら、デジタル出力をHight(ON)にします。その1秒後にデジタル出力をLow(OFF)にすることで、Hight(ON)の状態をリセットしています。
リセットしないと、振った後にHightのままになってしまいます。
動くタグの動作確認のために音も鳴らしています。
f:id:prince9:20180927030917p:plain

Arduino(M5Stack)コード
動きタグが振られたときが1、振られていないときは0をUnityに送っています。
シリアルモニタ代わりにM5Stackを使用しています。

#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(100); //0.1秒ごとにデータを出力。疲れないためにこの値を要調整
      M5.update();
}

「めっちゃ振ったらそのぶんだけ動く」=「めっちゃ振ったら大きく動く」ことで、Unityちゃんを走らせています。

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

public class UnitychanMoveScript : MonoBehaviour {

//Animator Contollerを処理するときのおまじない
private Animator animator;


	//new SerialPort("")にArduinoアプリで調べてメモしたシリアルポート名を指定する
SerialPort sp = new SerialPort("/dev/cu.SLAB_USBtoUART", 9600);

	// Use this for initialization
	void Start () {

//Animator Contollerを処理するときのおまじない
		animator = GetComponent<Animator>();

//シリアルポートが開いているか否か
		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) {
			
//Unityちゃんが走る
		 transform.position += transform.forward * 0.1f;
            animator.SetBool("Running", true);
		}
		else {

//振っていないときは止まる
            animator.SetBool("Running", false);
        }

//キーボードの左右キーで向きを変える
		if (Input.GetKey("right")) {
            transform.Rotate(0, 10, 0);
        }
        if (Input.GetKey ("left")) {
            transform.Rotate(0, -10, 0);
        }
		
		
	}
}