Leap Motion
Leap Motionは独自のセンサとカメラ技術により、人の手をセンシングするデバイスです。
安価で入手しやすいハンドトラッキングツールとして、発売から5年以上たった今でも人気のデバイスです。
Leap Motion リープモーションLM-C01-JP : yodobashi.com(現在は取り扱いなし)
SDK
Leap Motionを使った開発をする上で、以前は公式サイトから開発環境に応じたSDKを入手する必要があったようですが、現在はGitHubからダウンロードすることが出来ます。
UnityのSDKも4.5.0が最近アップデートされるなど、VRなどの用途からかまだまだ開発が続いていきそうです。
Assembly Definition
さて、Unityにはディレクトリ単位でAssemblyを分ける機能があり、ビルド時間短縮などのために自分のプロジェクトと3rdのライブラリのAssemblyを分けるために、Assembly Definition File(asmdef)を定義することがよく行われます。
上の記事でも
ライブラリや、スクリプトを含んだアセットを公開する場合はadfを定義してアセンブリを分割するべきです。
むしろやってくださいおねがいします。
とあるように、開発者がUnity向けにライブラリ開発を行う場合はAssembly Definitionを考慮して開発することが望まれます。しかし、LeapMotionのUnity向けライブラリには2020/5/16日時点で
Assembly Definition Fileは定義されていません。
Assembly Definition Fileは定義されていません。
😇
無いとどうなる
無くても問題ないでしょ?というのはもちろんそうです。LeapMotionの中の人たちもこのスタンスなのでしょう。
しかし、すでにAssembly Definitionを持った自分のプロジェクトにLeapMotionのSDKを突っ込みたくなった時問題になります。具体的には
- LeapMotionの定義を使用するAssemblyのディレクトリ内部でSDKを展開する
- つまり自プロジェクトと同じAssemblyに含めてしまう
- 自分でSDKのAssembly Definitionを設定する
の二択を迫られます。前者の場合で回避できるなら良いですが、Assembly Definitionの利点を殺しています。また、今後LeapMotionを必要とするAssemblyすべてに配置する必要が出てきます。
自分で定義
私が定義したAssembly DefinitionをGitHubに公開しています。
使ってみたい方は ここからunitypackageをダウンロード し、自分のUnityプロジェクトにimportしてください。
UnityModules-4.5.0のデフォルトからディレクトリ構成を変えていなければ、そもまま同じディレクトリに.asmdefが配置されます。
余談ですが、UniVRMでは.asmdefのみのunitypackageを分けてリリースしているようです。
注意
- 現状 4.5.0 の Core.unitypackage にしか対応していません。
- 将来LeapMotionが正式にAssembly Definitionに対応した場合、間違いなく競合します。
***
ここで「それでは良いLeapMotion+Assembly Definitionライフを」で終わってもよいですが、折角なので苦労話も載せておきます。
苦労話
さて、新しくAssembly Definitionを追加する場合、まず何をするでしょうか?
そう、とりあえず右クリックで[Create]->[Assembly Definition]から.asmdefを作りますね。
では、UnityModules-4.5.0の Assets/Plugins/LeapMotion/Core にLeapMotion.Core.asmdefを作ってみましょう。何が起こるでしょうか?ちなみにUnity のバージョンは2019.3.12です。
正解は603件のコンパイルエラーでした。
why?
LeapMotionは殊勝なことにSDKのテストをしっかり実装しており、テストコードもunitypackageに含めています。しかし、LeapMotion.Core.asmdefにて独自のAssemblyを定義したことにより、NUnit
などのテストのための定義が Assets/Plugins/LeapMotion/Core/ から参照できなくなってしまったのが原因です。
すべての定義が Assembly-CSharp
にある状態なら問題にならなかったのですが、Assembly Definitionにて Assets/Plugins/LeapMotion/Core 以下のディレクトリが独立したAssemblyになったため、NUnit
など必要な定義を参照できる設定を.asmdefにしてやる必要があります。
how?
LeapMotion.Core.asmdefの設定だけを良い感じにすればよいのでしょうか?
答えは No です。
全ての Tests/ のディレクトリにテスト用のAssembly Definition設定をする必要があります。
しかもこれ、以前(Unity2018.x)ではチェックボックスで切り替えれたのですが、2019.2からなくなりました。
2019.2 だとテスト関連の asmdef を参照させないとダメかな? #UniteTokyo #RoomD
— もんりぃ先生 (@monry) September 26, 2019
[Create]->[Testing]->[Tests Assembly Folder]で作ることはできますが、いくつもあるLeapMotionの Tests/ ディレクトリ全てにはとてもやってられません。
Unityの仕様上.asmdefが追加される度にコンパイルが走ってハングするので尚更です。
全ての Editor/ ディレクトリの.asmdefに platfrom=Editor
を定義してやる必要があります。
Assembly Definition無しなら Editor/ という名のディレクトリは自動でEditor専用のディレクトリとして認識されますが、Assembly Definitionを追加した場合、Editor/ 内に platfrom=Editor
になるように自分で.asmdefを設定しなくてはなりません。
なぜ[Create]->[Editor Assembly Definition]のような操作がないのでしょうね。こちらも1つ設定するたびにUnityがハングするのでとても手作業ではやってられません。
余談ですが、おそらく最短の platfrom=Editor
手動設定順は
- [Any Platformのチェックを外す]
- [Deselect all]
- [Editorのチェックを入れる]
- [Apply]
だと思います。
これキツくね?
私も手間がリターンに合わないと判断して一度は諦めました。しかし、できそうな手順を思いついたのでやってみました。キツかったですが詰んではなかったです。
.asmdefの自動生成
人間の温かみのある手作業で.asmdefを追加していくと毎回Unityがハングするので、Unityに気づかれないように.asmdefを一括で追加します。
LeapMotion/Core/ 以下にある Editor/ と Tests/ という名前のディレクトリを発見し、ディレクトリのパスに応じた名前の.asmdefを自動生成するエディタ拡張を実装しました。
例えば、 LeapMotion/Core/Scripts/Animation/Editor/ のディレクトリには LeapMotion.Core.Scripts.Animation.Editor.asmdef というAssembly Definition Fileが生成されます。
.asmdefの一括参照設定
.asmdefを追加しただけでは参照の設定がないのでコンパイルエラーは直りません。
人間の温かみのある手作業で.asmdefを一つ一つ編集するとそのたびにUnityがハングするので、LeapMotionとは別の個人開発でAssembly Definition Fileを同時に編集するエディタ拡張を作っていたので活用しました。
とはいえ、内部の依存関係はSDK開発者でない私にはわからないので、取り合えずは全ての.asmdefに LeapMotion.Core.asmdef への参照を追加し、以降はエラー内容を確認して対応しました。
流石はLeapMotion、Assembly Definitionこそ無かったものの破綻した依存関係にはなっておらず、苦労はしましたが.asmdefの設定に無事成功しました。これからは Frame
や Image
クラスを使いたいAssemblyにだけ LeapMotion.Core.asmdef の参照を追加すればよいのです。
おわりに
UnityのAssembly Definitionは便利で強力なのでもっと広く使われてほしいのですが、今回のようなややこしい問題に直面するとなると、正直まだ難しいのかなと思ってしまいます。
しかし、ライブラリ作成者は別です。Scriptを含む場合は是非Assembly Definitionを設定してください。