はじめに
移動できないUnityアセットはアセットの審査でリジェクトされてほしい。あと勝手に
— su10@ハイパーカジュアルゲーム開発 (@su10_dev) July 1, 2020
・Assets/Scripts
・Assets/Plugins
とかに入ってくるのも同様。
>・Assets/Scripts
— su10@ハイパーカジュアルゲーム開発 (@su10_dev) July 1, 2020
これは論外で、Assets/{アセット名とか}/ にすべき。
>・Assets/Plugins
これは Assets/{アセット名とか}/Plugins にすべきで、これ守ってないやつを毎回直すの面倒。
これらを守ってくれないと後から消したくなったときに苦痛(git revertはあるけど改造する場合もあるし)
これをつぶやいてから「いや、 Assets/Plugins はUnityの制限があるからしょうがなくない?」みたいなご指摘をいくつかいただいたので調べました(調べる前は「 Plugins は Resources と同じでどこにあっても・複数あっても同じ」という認識)。
結論から言うとUnityの仕様で Assets/Plugins に配置しないといけない場合がまだあったので諦めるしかない__場合もある__(Unityなんとかしてくれ😂)という話でした。
マニュアル記載の Assets/Plugins の挙動
マニュアルのいろんなページに散らばってるのですが、以下のそれぞれで Assets/Plugins に関する挙動が説明されています。
Plug-ins
プラグイン をプロジェクトに追加して Unity の機能を拡張することができます。プラグインは、通常は C/C++ で作成されたネイティブの DLL です。それらは、サードパーティのコードライブラリ、システムコール、その他の Unity ビルトイン機能にアクセスできます。Unity が検出できるように、プラグインは常に Plugins というフォルダーに配置してください。
1 つの Plugins フォルダーのみを持つことができ、プロジェクトのルートに配置する必要があります。Assets フォルダー内に直接配置します。
このフォルダーがスクリプトのコンパイルに与える影響の詳細については、特殊フォルダーとスクリプトのコンパイル順 を、異なるターゲットプラットフォームのプラグインの管理については Plugin インスペクター を参照してください。
定義済みのアセンブリ
Unityは、プロジェクトフォルダー構造内のスクリプトファイルの場所に基づいて、4 つの異なるフェーズでスクリプトをコンパイルします。各フェーズのために、別々の CSharp プロジェクトファイル (.csproj) と事前定義されたアセンブリが作成されます。任意のフェーズに適当なスクリプトがない場合、Unity は対応するプロジェクトファイルやアセンブリを作成しません。
スクリプトが、異なるフェーズでコンパイルされた (つまり、別のアセンブリにある) クラスを参照する場合、コンパイル順はとても重要です。基本的なルールは、現在のフェーズ の後に コンパイルされたものは参照できないということです。現在のフェーズ、またはそれ以前のフェーズでコンパイルされたものは、すべて参照可能です。
コンパイルの各フェーズは下記のとおりです。
| フェーズ | アセンブリ名 | スクリプトファイル |
|---|---|---|
| 1 | Assembly-CSharp-firstpass | Standard Assets、Pro Standard Assets、Plugins という名のフォルダー内のランタイムスクリプト |
| 2 | Assembly-CSharp-Editor-firstpass | Standard Assets、Pro Standard Assets、Plugins という名の最上位フォルダー内のあらゆる場所にある Editor という名のフォルダー内のエディタースクリプト |
| 3 | Assembly-CSharp | Editor という名のフォルダーに入っていないすべてのスクリプト |
| 4 | Assembly-CSharp-Editor | Editor という名のフォルダー内にある残りのすべてのスクリプト |

(↑Pathは Assets/MyPlugin/MyPlugin.dll になってる)
デフォルト設定
Unity は、プラグインが置かれたフォルダーに応じて、プラグインファイルのインポート設定のデフォルトを設定します。
| フォルダー | デフォルト設定 |
|---|---|
| (省略) | (省略) |
| Assets/Plugins/iOS | プラグインは iOS でのみ互換性があると判断されます。 |
| (省略) | (省略) |
Unityのマニュアルではないですが、こんなブログ記事もありました。
- Unity5からは"Assets/Plugins"フォルダは不要(けいごのなんとか)
Pluginsフォルダがありますけど名残というかわかりやすいようにしているだけです。Pluginsフォルダは必要ありません。
というわけで、 Assets/Plugins の仕様としては
- ネイティブプラグインはここに入れる必要がある
- コンパイルの順番に関係する(そもそも含まれるDLLに違いが出る)
の2点っぽいことがわかったので検証していきます。
若干古い気もしますがUnity2018.4.0f1にて行いました。
ネイティブプラグイン置き場として必須?
これについては先述の
プラグインは、通常は C/C++ で作成されたネイティブの DLL です。それらは、サードパーティのコードライブラリ、システムコール、その他の Unity ビルトイン機能にアクセスできます。Unity が検出できるように、プラグインは常に Plugins というフォルダーに配置してください。
を疑う形になりますが一応確認しておきます。インポート設定とファイルの配置を変えてiOS用にビルドしてみました。
Assets/Foo/ 以下で Any Platform の場合
含まれました(!)
Assets/Plugins/iOS 以下でいずれのプラットフォームにも含めない設定にした場合
↓結果
含まれてません。
* * *
というわけで、マニュアルのスクショを見てもそうであるように、ネイティブプラグインファイルが Assets/Plugins 以下である必要はなさそうです(インスペクタからの設定に依存する)。
コンパイルの順番に関係する?
配置場所によって含まれるDLLが違うということで、スクリプトを Assets/Foo/Plugins/ と Assets/Plugins/ にそれぞれ配置して、含まれるDLLを調べました。
一応それぞれの *.csproj を覗いてみましたがインスペクタに表示されたDLL側にちゃんと含まれてました。あと当然 Assets/Foo/Plugins から Assets/Foo/ にスクリプトを移動しても結果は変わりませんでした。
* * *
というわけで、 Assets/Plugins/ とそれ以外にスクリプトを配置した場合とでは違いがあることがわかりました。
まとめ
結論としては
- ネイティブプラグインの置き場所として
Assets/Plugins以下でなければならない制限はもうない - スクリプトが
Assets/Plugins以下だとコンパイル順に影響する-
Assets/Plugins/以下ならAssembly-CSharp-firstpass.dllに含まれる - つまり最初にコンパイルされる
-
ということになりました。
正直後者のメリットというかそうしなければならない理由が思い浮かばず、アセット作者の方々は前者のことを知らずに今でも惰性で Assets/Plugins 以下に入れてる場合が多いんじゃないかなと思いました(今だと asmdef でなんとかなるのでは?🤔)。
それと、【Unity】アプリに含めるアセットを抑えて、アプリサイズを小さくする(テラシュールブログ)によると
StreamingAssetsやPlugins/iOSやPlugins/Androidに含めたファイルは、そのまま含まれます。
とのことなので、もし Assets/Plugins に展開されるアセットがデモとかサンプルに画像を含みまくってたらビルド後のサイズが膨れそうなのでやめてほしいです(未検証)。
* * *
いろいろ書いてきましたがアセットを実際に作ってる方のほうが詳しいと思うので、間違い等あればご指摘ください。
あとコンパイル順に関して「 Assembly-CSharp-firstpass.dll じゃないとダメなんだぜ」というのがあればぜひ教えて下さい。

