LoginSignup
7
11

More than 1 year has passed since last update.

UnityとPython間でのデータのやり取り

Posted at

背景

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側でデータを読み書きするスクリプトを作る。

DataExchange.py
#実際に使うときはやり取りするデータは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スクリプトを作成する。

DataExchanger.cs
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に反映することであるため、推定にかかる時間を考慮すると問題ない程度であると言える。と思う。
Desktop-2021.07.15-00.47.26.01.gif

7
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11