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

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

女声から男声、女声(低)から女声(高)にボイスチェンジする

女声から男声はあまり資料がないので、もし成功された方はぜひメモを残してほしい・・・
というわけで、設定をミスったときのための自分メモです。
すべて無料のものを使っています。

ボイスチェンジのパターン

地声の女声(低)→男声のボイスチェンジ
地声の女声(低)→某エヴァのシンちゃん
地声の女声(低)→女声(高)

地声の女声(さらに低)→女声(もっと低)

でやってみました。

 

比較のための地声


私はわりと音域が広いようで、低い声からロリ声まで出ます(疲れますが)。
比較として、ガチの地声(低い女声)とロリな地声(高い女声)をまず用意しました。

・ガチの地声(低い女声)

・ロリな地声(高い女声)

 さらに低い地声はちょっと微妙だったので、掲載をパスしました。

ボイスチェンジ 女声→男声


・使用アプリは「恋声」→「REAPER」
恋声で変換とEQ、REAPERでノイズを取りました。REAPERで使用したのはVST「ReaFir」の「Subtract」のみ

恋声設定

f:id:prince9:20181022050237p:plain

f:id:prince9:20181022050212p:plain

 

ボイスチェンジ 女声→某エヴァのシンちゃん

使用アプリはREAPERのみ。ボイスチェンジはVSTの「RoVee」を使用

 

■REAPER設定

f:id:prince9:20181022050259p:plain

f:id:prince9:20181022050312p:plain

f:id:prince9:20181022050323p:plain

f:id:prince9:20181022050335p:plain

ボイスチェンジ 地声の女声(低)→女声(高)


これはロリ地声のほうがやはり良かったです。EQの設定が甘い感。自分のロリ声の波形に近づけるEQにしないとよくなりませんね。
使用アプリはREAPERのみ。ボイスチェンジはVSTの「RoVee」を使用しました。

■REAPER設定

f:id:prince9:20181022050358p:plain

f:id:prince9:20181022050409p:plain

f:id:prince9:20181022050418p:plain

f:id:prince9:20181022050429p:plain

ボイスチェンジ 地声の女声(さらに低)→女声(もっと低)

これが最もヘッドホンやスピーカーによって違いが出ました。あるヘッドホンだと良くても、あるスピーカーでは地声と変わらず・・・みたいな。

さらに低く発声した地声を恋声によってフォルマントのみ変更。
これが最もEQをいじくると結果が変わりました。

田中敦子さんみたいにしたかったと供述しており・・・

恋声で変換とEQ、REAPERでノイズを取りました。REAPERで使用したのはVST「ReaFir」の「Subtract」のみ。

恋声設定

f:id:prince9:20181022193443p:plain

f:id:prince9:20181022193457p:plain

VRChatやclusterでVR機器を使ってボイスチェンジする

最近流行りのボイスチェンジですが、意外と設定がややこしかったのでメモ代わりです。
VRChatとcluster(バーチャルルーム)で使用する想定です。
これらだけでなく、アプリ自体にサウンドの入出力設定の項目がない=デフォルトのサウンド設定を使うアプリも同様の設定でいけると思われます。
(VRChatやclusterなど、Unityベースのアプリ)
「VoiceMeeter Banana」のアプリは使用しません。

仮想サウンドミキサーの設定をする

1.下記から「VoiceMeeter Banana」をダウンロード&インストールする
www.vb-audio.com

2.Windowsサウンド設定の項目を開き、下記のように「再生」のタブに「Voice Meeter Aux Input」「VoiceMeeter Input」があるか確認する
f:id:prince9:20181021185832p:plain

3.今度は「録音」のタブに「Voice Meeter Aux Output」「VoiceMeeter Output」があるか確認する
f:id:prince9:20181021190011p:plain

4.「再生」のタブの「スピーカー」を右クリックし、「既定のデバイス」を選択する。Viveのイヤホン端子を既定のデバイスにする
f:id:prince9:20181021185832p:plain

5.「録音」のタブの「VoiceMeeter Output」を右クリックし、「既定のデバイス」を選択する

ボイスチェンジャーアプリの設定をする

1.ボイスチェンジャーアプリを立ち上げ、サウンド設定の項目を開く
2.下記のように設定する。双方とも同じで、Inputが「Viveのマイク(3-HTC Vive)」・Outputが「VoiceMeeter Input」
恋声など単体で動くアプリの場合:
f:id:prince9:20181021190622p:plain

VSTボイスチェンジャーの場合(:
f:id:prince9:20181021190659p:plain

恋声VSTで出力する場合(恋声のボイスをVSTでさらに加工する場合)
まず、こちらから「VB-Cable Virtual Audio Device」をダウンロード&インストールします
www.vb-audio.com


さらに、下記2つのアプリの設定をします。
恋声:
録音デバイス:「Viveのマイク(3-HTC Vive)」
再生デバイス:「CABLE Input」
↑すみません、スクショ撮り忘れです

VST使用可能アプリ(REAPERやCubaseなど):
f:id:prince9:20181021195946p:plain


3.ボイスチェンジできるようにしておく

StreamVRの設定

VRChatやclusterなど、ベースがUnityのアプリはデフォルトのサウンド設定を使うようになっています。
1.StreamVRを立ち上げ、「StreamVR▼」の▼をクリックし、「設定」を選ぶ
2.「設定」の「オーディオ」を選択し、下記のように設定する
f:id:prince9:20181021191045p:plain

3.VRChatもしくはclusterを立ち上げ、マイクをオンにする

UnityでiPhoneを使ってライトをコントロールする

下記ではMIDI機器を使用しましたが、今度はiPhoneでライトをコントロールしました。
prince9.hatenablog.com

ただタッチで細かい操作は事故りそうなので、個人的にはMIDI機器使用が確実と思われます。

f:id:prince9:20181016201155g:plain

プロジェクトファイルはこちらです。
www.dropbox.com

今回はOSCという通信規格を用います。Unityで使用するにあたり、hecomiさんのuOSCをお借りしました。
ありがとうございます。
tips.hecomi.com

iPhoneアプリ「TouchOSC」を使用する

※TouchOSC以外を使う場合は1.のみ行って、次の「OSCアプリの出力を調べる」に進んでください

1.使用するPCのIPアドレスを調べて、メモする
Macの場合:
minto.tech
WIndowsの場合:
https://laboradian.com/find-ip-on-windows10/laboradian.com
2.App Storeで「TouchOSC」アプリをダウンロードする
※「Mrmr」など無料のものもありますが、「TouchOSC」が個人的に使いやすかったです
3.立ち上げると下記のような設定画面が出てくるので、「CONNECTIONS」→「OSC」をタップする。
f:id:prince9:20181016195251p:plain
すでにUIが出ている場合は●ボタンを押す
f:id:prince9:20181016195526p:plain
4.「Host」に1.でメモしたPC側のIPアドレスを入力して、そのまま「完了」ボタンを押していく
f:id:prince9:20181016195411p:plain
5.「LAYOUT」を「Automat5」にする
6.右上の「Done」ボタンを押す

uOSCを読み込んで、OSCアプリの出力を調べる

1.下記にアクセスし、「.unitypackage」をクリックしてダウンロードする
github.com
2.Unityのプロジェクトを作成し、先ほどダウンロードした「.unitypackage」ファイルを「Assets」フォルダにドラッグ&ドロップする
3.「Import」ボタンを押して読み込む
4.「Assets」を右クリックし、「Create」→「C# Script」を選択する
5.4.に「OSCDataTestScript」等名前をつける
6.「GameObject」メニュー→「Create Empty」で空のオブジェクトを作成する
7.「Assets」フォルダ→「uOSC」→「Scripts」→「uOscServer」を「GameObject」にドラッグ&ドロップする
8.Hierarchyにある「GameObject」に「OSCDataTestScript」をドラッグ&ドロップする
9.Hierarchyにある「GameObject」をクリックし、「Inspector」→「Port」に「8000」と入力する
10.「Ctrl(Macはcommand) + Shift + C」キーを押して、コンソール画面を出す
11.「OSCDataTestScript」をダブルクリックして、下記のスクリプトを入力する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using uOSC;

public class OSCDataTestScript : MonoBehaviour {




	// Use this for initialization
	void Start()
    {
        var server = GetComponent<uOscServer>();
        server.onDataReceived.AddListener(OnDataReceived);
		
    }

    void OnDataReceived(Message message)
    {
        // address
        var msg = message.address + ": ";

      

        // values
        foreach (var value in message.values)
        {
            msg += value.GetString() + " ";
        }
        //どのUIかを出力
Debug.Log("どのUIか = " + message.address);

/*
下記のDebug.LogはUIを動かしてどんな値が出力されるのかを表示する。
アプリによってint・float・string・ byte[]いずれかで出力されるので、
分からない場合は下記の「(float)message.values[0]」の「float」を「int・string・ byte[]」いずれかに変えて、エラーが出ないものにすると良いかも。
stringの場合は、下記のように数値に変えてやる必要あり
文字列から数値へ変換:
float f1 = float.Parse("105.6");

 */
        Debug.Log("値 = " + (float)message.values[0]);
    }
	
	// Update is called once per frame
	void Update () {
		
		
	}
}


12.Unityの実行ボタン(再生ボタンみたいなやつ)を押す
13.TouchOSCなどのOSCアプリ(IPhoneアプリ)を立ち上げ、UIをタッチしてみる
14.Unityの「Console」ウィンドウに「どのUIを操作したか」「どんな値か」が表示されているのを確認する
f:id:prince9:20181016195135p:plain
15.すべてのUIをタッチして、「どのUIか」の値をメモっておく。「/toggleA_1」「/1/faderA」など

オブジェクトと照明を作成する

1.新しくプロジェクトを作成し、先ほどダウンロードした「.unitypackage」ファイルを「Assets」フォルダにドラッグ&ドロップする
2.「Import」ボタンを押して読み込む
3.適当にオブジェクトとライトをを配置して、名前をつける
4.「GameObject」メニュー→「Create Empty」で空のオブジェクトを作成する(ライトを増やすことを想定して)
5.4.に名前をつける(ここでは「Lights」にしました)
6.ライトを5.にドラッグ&ドロップする

スクリプトを書く

1.「Assets」フォルダ→「uOSC」→「Scripts」→「uOscServer」を「GameObject」にドラッグ&ドロップする
2.「Assets」を右クリックし、「Create」→「C# Script」を選択する
3.2.に「OSCTestScript」等名前をつける
4.Hierarchyにある「Lights」に「OSCTestScript」をドラッグ&ドロップする
5.Hierarchyにある「Lights」をクリックし、「Inspector」→Portに「8000」と入力する
f:id:prince9:20181016145826p:plain
6.「OSCTestScript」をダブルクリックして、下記のスクリプトを入力する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using uOSC;

//Lightsをクリックして、Portに「8000」と入力しておく
public class OSCDataTestScript : MonoBehaviour {
    //ライト指定
public GameObject slight1;


	void Start()
    {
        //OSC関連
        var server = GetComponent<uOscServer>();
        server.onDataReceived.AddListener(OnDataReceived);

        
    }

    void OnDataReceived(Message message)
    {
     

      //TouchOSCを使った場合、データはfloatで出る(toggleDataがデータ)
var toggleData = (float)message.values[0];

float LIntensity1 = slight1.GetComponent<Light>().intensity;
Color lightC1 = slight1.GetComponent<Light>().color;
      
      
        foreach (var value in message.values)
        {
            //処理を書く。「message.address == "/toggleA_1"」の「" "」の部分は「uOSCを読み込んで、OSCアプリの出力を調べる」14.の項目で
出力された値を入力する
            

            LIntensity1 = (message.address == "/toggleA_1" && toggleData == 1.0f) ? 10.0f //いちばん左下のトグル(ボタン)をOnにすると、ライトもOn
            : (message.address == "/toggleA_1" && toggleData == 0.0f) ? 0.0f //Offにすると、ライトもOff
            : (message.address == "/1/faderA") ? toggleData * 10.0f //いちばん左のスライダーを動かすと、ライトの明るさが変わる
            : slight1.GetComponent<Light>().intensity = LIntensity1; //他のボタンなどを操作したときはそのまま

            lightC1 =  (message.address == "/1/rotaryA") ? Color.HSVToRGB(toggleData, 1,1) //左上の半円のスライダー?を動かすと、色相(色味)が変わる
            : (message.address == "/toggleA_2" && toggleData == 1.0f) ? Color.HSVToRGB(0,0,1) //いちばん下の左から2番目のトグル(ボタン)をOnにすると、ライトの色を白にする
            :  (message.address == "/toggleA_2" && toggleData == 0.0f) ? Color.HSVToRGB(0,0,0)  //Offにすると、ライトの色が黒にする
            : slight1.GetComponent<Light>().color = lightC1;  //他のボタンなどを操作したときはそのまま

           


        }

        //最終的な照明の明るさと色
        slight1.GetComponent<Light>().intensity = LIntensity1;
        slight1.GetComponent<Light>().color = lightC1;
    }
	
	// Update is called once per frame
	void Update () {
        
	}
}

7.Hierarchyにある「Lights」をクリックし、Inspectorの「Slight 1」にライトをドラッグ&ドロップする
8.Unityの実行ボタンを押して、iPhoneのOSCアプリを動かしてみる

スクリプト解説

三項演算子による条件分岐

基本的には下記と同じですが、今回はライトのON/OFFを「Color.clear(色)」ではなく「intensity(明るさ)」の値で管理しました。
同様に「If〜else」「Swtich〜case」を使わず、三項演算子で短く条件分岐を書いています。
prince9.hatenablog.com

・ライトのON/OFFを三項演算子で条件分岐

float LIntensity1 = slight1.GetComponent<Light>().intensity;
 LIntensity1 = (message.address == "/toggleA_1" && toggleData == 1.0f) ? 10.0f //いちばん左下のトグル(ボタン)をOnにすると、ライトもOn
            : (message.address == "/toggleA_1" && toggleData == 0.0f) ? 0.0f //Offにすると、ライトもOff
 : slight1.GetComponent<Light>().intensity = LIntensity1; //他のボタンなどを操作したときはそのまま
slight1.GetComponent<Light>().intensity = LIntensity1;


・ライトの明るさを三項演算子で条件分岐

float LIntensity1 = slight1.GetComponent<Light>().intensity;
//いちばん左のスライダーを動かすと、ライトの明るさが変わる
 LIntensity1 = (message.address == "/1/faderA") ? toggleData * 10.0f
 //他のボタンなどを操作したときはそのまま
 : slight1.GetComponent<Light>().intensity = LIntensity1;
slight1.GetComponent<Light>().intensity = LIntensity1;

・ライトの色を三項演算子で条件分岐

Color lightC1 = slight1.GetComponent<Light>().color;
 //左上の半円のスライダー?を動かすと、色相(色味)が変わる
 lightC1 =  (message.address == "/1/rotaryA") ? Color.HSVToRGB(toggleData, 1,1)
 //他のボタンなどを操作したときはそのまま
            : slight1.GetComponent<Light>().color = lightC1; 
TouchOSCのどのUIを操作したか

「 "/toggleA_1"」はTouchOSCアプリのどのUIを動かしたかを示します。この場合は「いちばん左下のトグル(ボタン)」になります。
「"/1/faderA"」は「いちばん左の緑色のフェーダー」、「"/1/rotaryA"」は「いちばん左上の緑色の半円のUI」になります。
どのUIがどれに該当するのかは、「uOSCを読み込んで、OSCアプリの出力を調べる」14.の項目で調べています。
ちなみにTouchOSCの「Automat5」を使用した場合は、下記のようになります。
f:id:prince9:20181016200551p:plain

Unityで一定時間ごとに色(色相)を変える

OSCアプリやMIDIのフェーダでオブジェクトの色を変えようとしてた過程でできたので、忘れずにメモ。
Unityの公式リファレンスで「一定時間ごとにライトが明るくなったり暗くなったりする」というサンプルがありますが、それを改良した形です。
RGBで計算するとややこしいことになるので、色相(色味)のみを変えることにしました。
RGBからHSVへの正確な計算式もあるようですが、かなりややこしいのと使うのは照明程度なので今回はパスしました。
f:id:prince9:20181016055356g:plain

オブジェクトを設置する

1.「GameObject」メニュー→「3D Object」→「Cube」で適当にキューブを作る

スクリプトを書く

1.「Assets」を右クリックし、「Create」→「C# Script」を選択する
2.「HSVTestScript」等、名前をつける
3.Hierarchyにある「Cube」に「HSVTestScript」をドラッグ&ドロップする
4.Hierarchyにある「Cube」をクリックし、Inspectorの「HSVTestScript(script)」の中にある「Cube 1」を探す
5.「Cube 1」に、Hierarchyにある「Cube」ドラッグする
6.「HSVTestScript」をダブルクリックして、下記のスクリプトを入力する

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

public class ColorHSVrScript : MonoBehaviour {
//色が変わるタイミング(時間)を「Cube」のInspector(Duration)で指定、初期値は1.0F
public float duration = 1.0F;
//Hierarchyにある「Cube」を「Cube 1」にドラッグする(「Cube」のInspectorにあり)
	public GameObject cube1;

	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		//durationの時間ごとに色が変わる
		float phi = Time.time / duration * 2 * Mathf.PI;
		float amplitude = Mathf.Cos(phi) * 0.5F + 0.5F;
		//色をRGBではなくHSVで指定
		cube1.GetComponent<Renderer>().material.color = Color.HSVToRGB(amplitude, 1,1);
		
	}
}

UnityでMIDI機器を使ってオブジェクトと照明の色をコントロールする

VR上でのライブ演出の作業が必要となり、PCキーボードやマウス制御では事故ると思ってMIDI機器を引っぱり出しました。
いろいろ大変だったので、Keijiro Takahashiさんが作成された「MidiJack」をお借りして制御します。
今回はKORGの「nanoPAD1(初代)」を使いました。「nanoPAD2」や10月下旬に販売される新しいnanoPAD2でもいけると思います。

f:id:prince9:20181015231629g:plain

プロジェクトファイルはこちらです。
www.dropbox.com

※照明のところで、MIDIナンバーのコメントが一部違っています。このサイトに掲載しているスクリプトは修正済みです。スクリプトの実行に影響はないですが、すみません

※2 三項演算子と「Input.GetKeyDown」「Input.GetKeyUp」の相性が極めて悪いようです。
これらを使う場合は、素直に公式の下記を使います。
docs.unity3d.com


下記はMIDI機器のドライバがすでにインストール済みとして進めます。

MidiJackを読み込む

1.下記のURLにアクセスする
github.com

2.緑色のボタンの「Clone or Download」をクリックし、「Download ZIP」をクリックしてダウンロードする
3.ダウンロードしたものを解凍する
4.プロジェクトを作成し、「MidiJack-master」フォルダ→「MidiJack.unitypackage」をUnityの「Assets」フォルダにドラッグ&ドロップする
5.「Import」ボタンを押して読み込む

オブジェクトと照明を作成する

1.適当にオブジェクトと照明をを配置して、名前をつける
f:id:prince9:20181015211143p:plain

2.「GameObject」メニュー→「Create Empty」で空のオブジェクトを作成する
3.2.に名前をつける(ここでは「Cubes」にしました)
4.オブジェクトと照明を3.にドラッグ&ドロップして、下記のような構成にする
f:id:prince9:20181015211554p:plain

スクリプトを書く

5.「Assets」を右クリックし、「Create」→「C# Script」を選択する
6.5.に「MIDITestScript」等名前をつける
7.Hierarchyにある「Cubes」に「MIDITestScript」をドラッグ&ドロップする
8.「MIDITestScript」をダブルクリックして、下記のスクリプトを入力する

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MidiJack;

//https://github.com/keijiro/MidiJack

//注意: 下記の「MIDITestScript」がファイル名と同じかチェックする。違う場合はファイル名に書き直す
public class MIDITestScript : MonoBehaviour {
	

//「Cubes」をクリックしてInspectorを開き、mycubeオブジェクト3つとSpot Lightオブジェクト3つをドラッグする
public GameObject cube1,cube2,cube3,slight1,slight2,slight3;

/* 
色を配列に登録
        UnityではRGB値で指定できないので、RGB値の後に「f/255f」をつける
        例: RGB値 165,42,42(茶色)
           public Color Brown = new Color(165f/255f,42f/255f,42f/255f);
        */

//キュープ用の色の配列
Color[] collors = new Color[] { Color.white,Color.red, Color.green, new Color(0f/255f,206f/255f,209f/255f)};

//照明用の色の配列、照明を消すには「Color.clear」を使っているのでちょっと無理やり感
Color[] lcollors = new Color[] {Color.clear,Color.green, Color.yellow, new Color(188f/255f,6f/255f,12f/255f)};

	void NoteOn(MidiChannel channel, int note, float velocity)
    {
        //Debug.Log("NoteOn: " + channel + "," + note + "," + velocity);

         Color c1 = cube1.GetComponent<Renderer>().material.color;
          Color c2 = cube2.GetComponent<Renderer>().material.color;
           Color c3 = cube3.GetComponent<Renderer>().material.color;

            Color lightC1 = slight1.GetComponent<Light>().color;
            Color lightC2 = slight2.GetComponent<Light>().color;
            Color lightC3 = slight3.GetComponent<Light>().color;



//下記、三項演算子を使った条件分岐(キューブの色)          
c1 = (note == 39) ? collors[1] //nanoPadの1
: (note == 36) ? collors[0] //nanoPadの7
: cube1.GetComponent<Renderer>().material.color = c1; //その他のキーが押されたとき、状態を保持

c2 = (note == 48) ? collors[2] //nanoPadの2
: (note == 38) ? collors[0] //nanoPadの8
: cube2.GetComponent<Renderer>().material.color = c2; //その他のキーが押されたとき、状態を保持

c3 = (note == 45) ? collors[3] //nanoPadの3
: (note == 40) ? collors[0] //nanoPadの9
: cube3.GetComponent<Renderer>().material.color = c3; //その他のキーが押されたとき、状態を保持

cube1.GetComponent<Renderer>().material.color = c1;
cube2.GetComponent<Renderer>().material.color = c2;
cube3.GetComponent<Renderer>().material.color = c3;

/* 
上記を条件分岐の「if」で書き直すとこちら
if(note == 39)
    {
     cube1.GetComponent<Renderer>().material.color = collors[1];
    }
    else if(note == 36)
    {
    cube1.GetComponent<Renderer>().material.color = collors[0];
    }

    〜略
*/

/* 
上記を条件分岐の「switch〜case」で書き直すとこちら
switch (note) {

    case 39: 
        cube1.GetComponent<Renderer>().material.color = collors[1];
        break;

    case 36:   
        cube1.GetComponent<Renderer>().material.color = collors[0];
        break;

    〜略

    default:    
        Debug.Log("エラー");
        break;
}
*/

//下記、三項演算子を使った条件分岐(照明の色)         
lightC1 = (note == 43) ? lcollors[1] //nanoPadの4
: (note == 42) ? lcollors[0] //nanoPadの10
: slight1.GetComponent<Light>().color = lightC1; //その他のキーが押されたとき、状態を保持

lightC2 = (note == 51) ? lcollors[2] //nanoPadの5
: (note == 44) ? lcollors[0] //nanoPadの11
: slight2.GetComponent<Light>().color = lightC2; //その他のキーが押されたとき、状態を保持

lightC3 = (note == 49) ? lcollors[3] //nanoPadの6
: (note == 46) ? lcollors[0] //nanoPadの12
: slight3.GetComponent<Light>().color = lightC3; //その他のキーが押されたとき、状態を保持

slight1.GetComponent<Light>().color = lightC1;
slight2.GetComponent<Light>().color = lightC2;
slight3.GetComponent<Light>().color = lightC3;

/* 
長くなるが、こちらのほうが無理がなくていいかも
if(note == 43)
    {
     slight1.SetActive(true);
    }
    else if(note == 42)
    {
    slight1.SetActive(flase);
    }
*/

  
    }

    void NoteOff(MidiChannel channel, int note)
    {
       
		Debug.Log("NoteOff: " + note);
    }

 

	void OnEnable()
    {
        MidiMaster.noteOnDelegate += NoteOn;
        MidiMaster.noteOffDelegate += NoteOff;
        
    }

    void OnDisable()
    {
        MidiMaster.noteOnDelegate -= NoteOn;
        MidiMaster.noteOffDelegate -= NoteOff;
        
    }


	// Use this for initialization
	void Start () {
  	
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

スクリプト解説 三項演算子

nanoPadのボタンに割り振られている番号(MIDIナンバー)がバラバラだったため、やむなく条件分岐で処理を書くことにしました。
switch〜caseやif〜elseなどを使えば楽なのですが、スクリプトが長くなりがちです。
今回はこれら条件分岐を短めに書く「三項演算子」を使いました。
注意点としては、演算子なのでif〜elseの「else」に該当する部分が省略できないことです。

以下、例1-3すべて同じ動きをします。

例1: if文

string s;
        if (note == 39)
        {
            s = "No.1 0n";
        }
        else if (note == 48)
        {
            s = "No.1 0ff";
        }
        else {
            s = "Other 0ff";
        }

例2: switch文

string s;
switch (note) {
	case 39:
		 s = "No.1 0n";
		break;
	case 48:
		s = "No.1 0ff";
		break;

	default:
		s = "Other 0ff";
		break;
}

例3: 三項演算子

string s;
s = (note == 39) ? "No.1 0n"
: (note == 48) ? "No.1 0ff"
: "Other 0ff";

swtich文と比較すると分かりやすいかと思われます。

= (演算子の式1) ?  式1の条件が真のときの処理
:  (演算子の式2) ? 式2の条件が真のときの処理
: すべてが当てはまらないときの処理;


となっています。

スクリプト解説 照明の色について

ifやswitchを書かないようにしていたので、「Color.clear」で無理やり照明を消しています。これに関してはifかswitchを使って、「slight1.SetActive(trueまたはfalse);」にしたほうがよかったかもしれません。

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);
        }
		
		
	}
}

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;

		}

		
	}
}