#背景
Unityで計測したデータをPythonに送って、機械学習で推定した結果を可能な限りリアルタイムでUnity側に反映させたかったが、調べてもサーバーを使うものしか見つからず、リアルタイムにやり取りできなかった.
#目的
可能な限りリアルタイムでUnityとPythonでデータをやり取りする.
UnityとPythonのコード:https://github.com/sakamo1290/DataExchange
Unity:2019.4.28f1
Python:3.7.6
#方針
csv(Unity2Python.csvとPython2Unity.csv)を介してデータをやり取りする.
#実装
Unity側でFixedUpdateが呼び出されるたびにインクリメントされる変数(count)をcsvを介してやり取りする。
###Python側
まずPython側でデータを読み書きするスクリプトを作る。
#実際に使うときはやり取りするデータは1つではないため、pandasのDataFrameでcsvに読み書きする
import pandas as pd
def main():
#Unityから送られてきたデータを格納するDataFrame
log = pd.DataFrame(columns = [0], index = [0], data = [0])
#データが更新されているかを確認するための変数
past = -1
while True:
past, log = ReadData(past, log)
WriteData(past)
def ReadData(past, log):#Unityからデータを受け取る
#データをUnityが書き込んでいるときはアクセスできずエラーになるためtryで回避
try:
a = pd.read_csv('Unity2Python.csv', encoding="ms932" ,sep=",")
except:
return past, log
#データが更新されていない場合読み取りを終了する
if past == a.columns[0]: return past, log
log = log.append([int(a.columns[0])])
print(a.columns[0])
past = a.columns[0]
return past, log
def WriteData(past):#Unityにデータを送る
#Unityが読み込んでいるときはアクセスできずエラーになるためtryで回避
try:
pd.DataFrame([past]).to_csv(path_or_buf = 'Python2Unity.csv', header=False, index=False)
except:
return
if __name__ == "__main__":
main()
###Unity側
Unity側でもデータをやり取りするスクリプトを作成する(gitのDataExchange.unitypackage内に完成したものが入れてある)。
新しいプロジェクトを作成し、ヒエラルキーで右クリックして'Create Empty'を選択する。
名前を'DataExchanger'にしてインスペクターで'Add Component'をクリックしDataExchangerスクリプトを作成する。
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class DataExchanger : MonoBehaviour
{
int count = 0;
string sendDataPath;
string recieveDataPath;
void Start()
{
sendDataPath = Application.dataPath + "/LogData/Unity2Python.csv";
recieveDataPath = Application.dataPath + "/LogData/Python2Unity.csv";
}
void FixedUpdate()
{
WriteData(count.ToString(), sendDataPath);
ReadData(recieveDataPath);
count++;
}
void WriteData(string data, string _filePath)
{
string _path = _filePath;
StreamWriter sw;
FileInfo fi;
fi = new FileInfo(_path);
sw = fi.CreateText();
sw.WriteLine(data);
sw.Flush();
sw.Close();
}
void ReadData(string _filePath)
{
Debug.Log(File.ReadAllText(_filePath));
}
}
###DataExchange.pyを配置
Unityのフォルダ内にAssets/LogDataとなるようにLogDataフォルダを作成する。
LogDataフォルダ内にDataExchange.pyを配置する(場所はここでなくても問題ないが簡単のために。変える場合はスクリプトのパスを修正する。)。
#動作確認
おおむねよく動いているが、Unity側で数字が飛ぶ場合がある。
目的は機械学習の結果をUnityに反映することであるため、推定にかかる時間を考慮すると問題ない程度であると言える。と思う。