UnityからPythonモジュールを呼び出す【Python.NET】
はじめに
pythonnet (Python.NET) を使用して,Unity上でPythonモジュールを呼び出す方法をまとめました.Pythonの豊富な機械学習系のライブラリとUnityのゲームエンジンを組み合わせて使いたいときに有用です.
pythonnetをUnity上で使用する解説記事がないのが現状で,クラッシュ報告もあるため,記事を作成しました.
Python.NETとは?
pythonnetは,.NETからPython (CPython) コードを呼び出すことができます.反対に,Pythonコードから.NETを呼び出すことも可能です.一方,IronPythonは,python3.x系の開発が進んでいなかったり,CPythonとの互換性も十分でなかったりと,本用途には適していません.
pythonnetの特徴は,Pythonコードから中間言語を生成せず,CPythonと.NET / Monoを統合するため,Pythonコードのネイティブ実行速度を維持したまま.NETの機能を使用することができます.(IronPythonはマネージコード実装)
準備
まずは,pythonnetをビルドします.githubリポジトリからcloneして,ソリューションファイルpythonnet.slnを開きます.
pythonnet.slnから,Python.Runtime.dll
をビルドします.ビルド方法やその他の環境構築については,こちらの記事に詳しくまとめられています.
作成したPython.Runtime.dll
をUnityプロジェクトにインポートし,Api Compatibility Level
を.NET 4.x
に変更します.
サンプルコード
以下は,numpyモジュールをUnity上で実行した例です.
PythonEngine.Initialize()
の引数を設定しない場合,このissueにあるように,二回目実行時にクラッシュします.
using System.Collections.Generic;
using UnityEngine;
using Python.Runtime;
void Start()
{
PythonEngine.Initialize(mode: ShutdownMode.Reload); // 初期化
using (Py.GIL()) // Global Interpreter Lockを取得
{
dynamic np = Py.Import("numpy");
// ndim: 1
dynamic a = np.array(new List<float> {1.0f, 2.0f});
Debug.Log(a.shape);
Debug.Log(a*a);
// ndim: 2
dynamic b = np.array(new List<List<float>> {new List<float> {1.0f, 2.0f}, new List<float> {3.0f, 4.0f}}, dtype: np.float64);
Debug.Log(b.shape);
Debug.Log(b*b);
}
PythonEngine.Shutdown(); // python環境を破棄
}
次の記事では,PythonモジュールとUnityの3Dオブジェクトを組み合わせた実装を紹介したいと思います.
Discussion