Unity におけるマネージドプラグインの参照問題
概要
この記事では、Unity におけるマネージドプラグインの参照についての問題と対処を書きます。
背景
Unity のプロジェクトに NuGet のパッケージをインポートするエディタ拡張を作ったよ
起こる問題
以下のように同じフォルダになく、参照するバージョンが違うアセンブリがあるときに起きます。
Assets
│
├─packageA.1.0.0
│ └─packageA.dll #packageC.dllのバージョン1.0.0以降に依存
│
├─packageB.1.0.0
│ └─packageB.dll #packageC.dllのバージョン1.1.0以降に依存
│
└─packageC.1.1.0
└─packageC.dll
この状態で、Plugin importer の Validate references が有効なときはエディタ上で、無効のときは実行時に FileNotFoundException
が発生します。この状態でビルドすると、出力された実行ファイルは問題なく動きます。
調査
Validate references というのが今まで見なかった物なので調べましたが、Unity2019 から出てきたものという情報以外はありませんでした。いろいろ試した結果、アセンブリのリロード時に依存解決を試み、問題があればエラーを出すような動きをしました。
次に、C# でランライムはどのようにアセンブリをロードしているかを調査しました。以下の手順で行っているみたいです。
- アプリケーション構成ファイル[1]を検索し、そのファイルに書いてある依存関係を利用。
- Global Assembly Cache (GAC) を検索。
- アセンブリ名を元に実行ファイルと同じディレクトリを検索。
これらは Unity で操作する領域ではないので、Unity 独自のアセンブリの依存解決法に頼るしかありません。
では、どうしようもないのかというとそうではなく、同じディレクトリ内であればバージョンが完全一致しなくても読み込めます。対象は呼ぶアセンブリと呼ばれるアセンブリです。 (謎挙動といえば謎挙動) 原因がわかりました。(21/12/04追記)
原因
Validate references の 実装をながめてて気づいたのですが、アセンブリが同じフォルダ内にある場合のみバージョンのチェックが無視されるみたいです。つまり、バージョンが完全一致しないアセンブリは、同じフォルダに置くか、Project Settings -> Player -> Other Settings -> Assembly Version Validation
のチェックを外すのどちらかをしないといけないみたい。
結論
マネージドプラグインは一つのディレクトリにまとめておくと無難。もしくはプロジェクトの設定でアセンブリのバージョンチェックを行わないようにするか。
あとがき
対処するだけなら簡単だけどかっこわるく、きれいな方法が今のところなくて、うまい方法がないと言うのにかなり調べないといけなかったのがつらかった。(ちゃんとドキュメントがあった。調査不足。)Unity さんどうにかしてくれないかな。
参考資料
- ランタイムがアセンブリを検索する方法
- Assemblies and the GAC
- インサイド .NET Framework [改訂版]第3回 アセンブリのロード
- Unity - Manual: Import and configure plug-ins
-
アプリケーション構成ファイルは hoge.exe という実行ファイルであれば hoge.exe.config というように、実行ファイルに .config をつけたものとなっている。 ↩︎
Discussion