ESP32からUnityへWiFiでデータ送信したい

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) 理解のためのメモ


#やること
ESP32からUnityへ、WiFiのアクセスポイント経由でデータを送信します。
UDPパケットを使います。
今回はESP32が送信、Unityが受信に一方向のみの通信です。

送信するデータ形式は符号あり2バイトのShort型が配列で10個並んだものです。
これを1バイトずつ送り、Unity側で受信後に2バイト数値に戻します。

Unity側ではインスペクターに受信データを表示します。

#記事アップデート
https://qiita.com/Ninagawa_Izumi/items/59b56bcf7a9d13961a4f
送受信に対応したバージョンはこちらになります。

#ポイント
- ESP32側では2バイトを1バイトに変換するために共用体を利用
- Unity側では近い処理をBitConverterで実施
- Unity側の受信処理はスレッドを立てて実行


#参考
https://github.com/devemin/UDPesp32unity

今回の記事はほぼこちらのトレースであります。ありがたく勉強させていただきます。

#ESP32用スクリプト

```C++:Arduino
#include <WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "SSID";//WiFiアクセスポイントのSSID
const char* password = "password";//WiFiアクセスポイントのパスワード
const char* client_address = "PCのIPを調べて入力";//送信相手のPCのIP
const int client_port = 22222;  //送り先のポート番号
const int server_port = 22224;  //ESP32のポート番号

WiFiUDP udp;

//送るデータのサイズ。データはショート型の符号付き２バイト、送信時は１バイトに変換。
static const int MSG_SIZE = 10;//送信データの数
static const int MSG_BUFF = MSG_SIZE * 2;//送信データのバイト数

//共用体の設定。共用体はたとえばデータをショートで格納し、バイト型として取り出せる
typedef union {
  short sval[MSG_SIZE];//ショート型
  uint8_t bval[MSG_BUFF];//符号なしバイト型
} UDPData;
UDPData s_upd_message_buf; //共用体のインスタンスを宣言

int count = 0;//送信変数用のカウント

void setup() {
  Serial.begin(115200);
  delay(500);//シリアル準備待ち用ディレイ
  //WiFi 初期化
  WiFi.disconnect(true, true);//WiFi接続をリセット
  Serial.println("Connecting to WiFi to : " + String(ssid));//接続先を表示
  delay(100);
  WiFi.begin(ssid, password);//Wifiに接続
  while ( WiFi.status() != WL_CONNECTED) {//https://www.arduino.cc/en/Reference/WiFiStatus 返り値一覧
    delay(100);//接続が完了するまでループで待つ
  }
  Serial.println("WiFi connected.");//WiFi接続完了通知
  Serial.print("WiFi connected. ESP32's IP address is : ");
  Serial.println(WiFi.localIP());//デバイスのIPアドレスの表示

  //UDP 開始
  udp.begin(server_port);
  delay(500);
}

//送信用の関数
void sendUDP() {
  String test = "";//表示用の変数

  udp.beginPacket(client_address, client_port);//UDPパケットの開始

  for (int i = 0; i < MSG_BUFF; i++) {
    udp.write(s_upd_message_buf.bval[i]);//１バイトずつ送信
    if (i % 2 == 0) {//表示用に送信データを共用体から2バイトずつ取得
      test += String(s_upd_message_buf.sval[i / 2]) + ", ";
    }
  }
  Serial.println("[SEND] " + test );//送信データ（short型）を表示

  udp.endPacket();//UDPパケットの終了
}


void loop() {

  //送信するデータを作成
  for (int i = 0; i < MSG_SIZE; i++) {
    s_upd_message_buf.sval[i] = (short)( i + count);
  }

  sendUDP();//UDPで送信
  
  count += 10;//データ作成用のカウントを追加
  if (count > 10000) {
    count = 0;
  }
  
  delay(500);
}

```

まずこちらのスケッチをESP32に書き込みます。
実行直後（リセット直後）に、シリアルモニタにESP32のIPアドレスを表示し、
その後は送信データを表示し続けます。


#Unity用スクリプト

```C#:udp_receive_test.cs
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;

public class udp_receive_test : MonoBehaviour
{
    int LOCAL_PORT = 22222;//受信に使うポートの番号
    static UdpClient udp;//UDPを使う準備
    Thread thread;//スレッドを使う準備

    const int datanum = 10;//受信するshort型データの個数
    static char[] c_buf = new char[datanum * 2];//データ受信用のchar型変数（１バイト）
    static short[] s_buf = new short[datanum];//データ格納用のshort型変数（２バイト）
    public int[] showdata = new int[10];//インスペクタ表示用


    void Start()
    {
        udp = new UdpClient(LOCAL_PORT);
        udp.Client.ReceiveTimeout = 1000;//UDP通信のタイムアウト設定
        thread = new Thread(new ThreadStart(ThreadMethod));//受信用スレッドを準備
        thread.Start();//受信用スレッドを開始
    }


    void Update()
    {
        //受信データをインスペクターに反映
        for (int i = 0; i < datanum; i++)
        {
            showdata[i] = s_buf[i];//受信データをpublic配列に転記
        }
    }


    void OnApplicationQuit()//アプリ終了時の処理
    {
        thread.Abort();
    }


    private static void ThreadMethod()//受信スレッド用の関数
    {
        while (true)
        {
            IPEndPoint remoteEP = null;
            byte[] data = udp.Receive(ref remoteEP);

            //パケットサイズをチェックし、受信データをUnityに反映
            if (data.Length == datanum * 2) // 
            {
                for (int i = 0; i < datanum; i++)
                {
                    s_buf[i] = BitConverter.ToInt16(data, i * 2);
                }
            }
        }
    }
}

```

#使い方と実行
・Unityの新規プロジェクトを立ち上げます。
・アセットに新規スクリプトを作成してファイル名を「udp_receive_test」とし、上記のスクリプトをコピペします。
・ヒエラルキーウィンドウに空のオブジェクトを作成し、スクリプトをアタッチします。
・空のオブジェクトを選択し、インスペクターを表示します。
・スケッチが書き込まれたESP32を起動します。
・インスペクターにカウントアップする数値が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/ae20c0e8-8009-5447-e123-661850a99a16.png" width = 300>


#おわりに

次回記事：[ESP32とUnityをWiFi送受信で連携する](https://qiita.com/Ninagawa_Izumi/items/59b56bcf7a9d13961a4f)
→逆方向の送受信にも対応しました。