📘

UnityからPythonモジュールを呼び出す【Python.NET】

2022/05/14に公開

はじめに

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オブジェクトを組み合わせた実装を紹介したいと思います.

参考文献

pythonnet.github.io
.NET (C#)からpythonを呼び出す

GitHubで編集を提案

Discussion