勉強不足で至らんブログ

勉強不足ですが色々と書いていきます。

UnityのStreamingAssets内でPython環境構築してみた

Pythonで作られたライブラリなどをUnityでも流用したい!

ということで思いついたのがPythonに必要なファイルを全て StreamingAssets に突っ込む方式でした。

その前にクライアント/サーバーでやり取りしろよ!って話ではあります。はい。その通りです!ただスタンドアローンで動かしたかったんです!!

PythonC#のやり取りをする

github.com

C#との連携で他にもツールは出てきたのですが最終的にPythonのライブラリも使いたいと思っており、探すとPythonnetならできるという情報があったので選出しました。

GithubWikiに導入方法などは書いておりスムーズに導入できました。dllをダウンロードしてPluginsディレクトリに入れるだけですね。

中身を弄る必要があればGitHubから簡単にcloneしてdefineを弄ればUnityで動かすカスタムができる印象でした。

突っ込むPythonの環境を取得する

Pythonの環境はAnacondaで取得した環境をStreamingAssetsに入れることにしました。 Pythonのインストールパスを確認してから

Python
|---------DLLs
|---------Lib
|---------Scripts
|-たくさんのdllとpyファイル

をUnityのStreamingsAssetsに入れます。基本的に必要なものは上記でした。他のディレクトリは無くても大丈夫です。

Editorでは動きます。

Editor/Buildの違い

Unity Editorでは Plugins ディレクトリ以外にdllがあっても読み込んでくれます。そのため StreamingAssetsPythonのすべてを入れておくだけでPythonが動きます。しかし、BuildをしてStreamingAssetsにPythonを入れてもdllを検知できません。そのため、Pythonを動かすのに必要なdllをPluginsにいれて他の.pyなどをStreamingAssetsに入れることで解決しました。

そのためdllを全てPluginsに入れて他をStreamingAssetsに入れるようにします。細かいことを気にしなければ全部 PluginsStreamingAssets に入れてしまいます。

ちゃんと分けたい場合は

StreamingAssets

find . -name "*.dll" -type f | xargs rm

などをして必要な拡張子だけを残すようにします。 Plugins だと exepy など dll 以外を消す必要があります。(Windowsだと)

動かした結果

using周りは端折りますが以下のコードを動かしました。(.Net4.0環境)

public class PythonLifeCycle : IDisposable
    {

        public void Initialize()
        {
            
            var pythonHome = $"{Application.streamingAssetsPath}/PythonEnv";


            var scripts = $"{pythonHome}/Scripts";
            
            Environment.SetEnvironmentVariable("PATH", $"{pythonHome};{scripts}", EnvironmentVariableTarget.Process);
            Environment.SetEnvironmentVariable("DYLD_LIBRARY_PATH", $"{pythonHome}/Lib", EnvironmentVariableTarget.Process);

            PythonEngine.PythonHome = $"{pythonHome}";
            PythonEngine.PythonPath = $"{pythonHome}/Dlls;{pythonHome}/Lib;{pythonHome}/Lib/site-packages";
            
            PythonEngine.Initialize();
        }

        public void Dispose()
        {
            PythonEngine.Shutdown();
        }
private readonly PythonLifeCycle lifeCycle = new PythonLifeCycle();
        [SerializeField] private TextMeshProUGUI textUI;

        void Start()
        {
            lifeCycle.Initialize();

            RunPython();
        }

        private void RunPython()
        {
            using (Py.GIL())
            {               
                dynamic sysModule = Py.Import("sys");
                
                textUI.text = sysModule.version;
            }
        }

        private void OnDestroy()
        {
            lifeCycle.Dispose();
        }

シンプルにPythonの環境を構築してTextを出力するようにしています。

Editor Windows
f:id:MakeTake:20200906101448p:plain f:id:MakeTake:20200905224738p:plain

最低限Editor/Buildでの差は埋めれました。 他(WebGL/Android)はそのまま動かなかったので放置しています。一旦はWinのみで開発するつもりだったので。 触った感じだとデスクトッププラットフォームだと問題ないと思います。

WebGLで実行とエラーがでるのですがパッとうまい解決策が見つけれず放置 Androidでビルドしてgradleの処理の際にStreamingAssetsのファイルが多すぎてファイルをすべてgroovyのファイルに記述されていて、その記述されている数が多いことでエラーとなり失敗します。これはzipに纏めるなりの回避をすればなんとかなるとは思います。(メモ)

まとめ

今後はpythonのライブラリを導入してC#から使えるようにしていこうと思います。1プラットフォームでもPythonを内蔵して動いて良かったです。