SteamVR2.x対応のときにAssembly Definition Fileを使った話

バーチャルキャストクライアント開発のえんぺるです。
今年の夏に、バーチャルキャストはSteamVRのバージョンを2.3.2にアップデートしました。これによってこれまで対応してなかったコントローラーもユーザーが設定を作ることで一時的に対応できるようになったり、一部の入力をユーザーが編集できるようになりました。

例えば、アイテムを掴む時はViveコントローラーの時はトリガーだったけどOculusではグリップでつかみたいとか、アイテムを使うときはAボタンにしたいとか、そういう変更をSteamVRのメニュー上でユーザーがそれぞれ好みに合わせて変更することができるようになりました。

(ユーザーがすでにIndexコントローラーの非常に良い設定を公開してくれています。感謝…!)

SteamVR1.x to 2.x

既に運用されているアプリケーションを、SteamVR1.x から 2.x へバージョンアップするのはそれなりに大変です。
SteamVRの推奨するワークフローは、まずプロジェクトに導入している1.xを削除した後に2.xをインポートして2.xのセットアップを新規アプリケーションと同じように行う事です。当然ですがその場合元々1.xを参照していたPrefab等はMissingになったりしますし、APIの様々な変更も同時に対応しなくてはなりません。

数多くのエラーを同時に解決するのはなかなか骨が折れます。バーチャルキャストはそこそこ大きなアプリケーションなので、これを一気にえいやとするとコードレビューする側もその大きな変更に圧倒されてレビューする事ができなくなってしまいます(結局最後には巨人みたいなプルリクエストが飛んでくる事になるんですがそれはまた別の話…)

一気に解決か?段階的にか?

大量のエラーを前にして一個一個手作業で直すのは正直厳しい。気合と根気でやった結果だめだったとかは地獄の極みなのでそれはやりたくはないですし、何よりプルリクエストを投げた時にレビュワーがレビューできない粒度のものになってしまいます。

AssemblyDefinitionを試してみた

スクリプトのコンパイルとアセンブリ定義ファイル
https://docs.unity3d.com/ja/current/Manual/ScriptCompilationAssemblyDefinitionFiles.html

Unity2017.3から導入されたAssemblyDefinitionというUnityの機能があります。
これはAssemblyDefinitionの定義ファイルがあるディレクトリ以下を別のアセンブリに分ける事ができる機能です。
よく聞くメリットとしてはアセンブリが分かれる事でコンパイル時間の短縮になる事なんですがこの機能を使えばプロジェクト内に1.xと2.xが存在していてもエラーにならず共存させることができます。

これで対応中は動作不十分になるものの段階的に対応できる下地ができました。また、何か動作に問題が起きた際にも1.xを消したわけではないので以前の実装に戻して比較する事も可能です。

Assembly Definition Fileを活用したSteamVRアップデートの流れ

さて、AssemblyDefinitionの仕組みを使えば共存は行けそうなので対応していきます。
対応の手順は次になります

  1. プロジェクトにすでにあるSteamVR1.xのディレクトリにAssembly Definition Fileを作成する(以下v1.asmdef)
  2. SteamVRを参照しているスクリプトがあるディレクトリにAssembly Definition Fileを作成してv1.asmdefを参照に追加する。
  3. プロジェクトにSteamVR2.xをインポートする(SteamVR2.xはあらかじめAssembly Definition Fileがある為作成は不要)
  4. エラーが起きない事を確認できたら準備完了です。順次対応していきましょう。

対応例:入力の対応

SteamVR2.xで大きく変わったのは入力周りです。
どう変わったのかというところは今回解説はしませんがドキュメントに載っている画像がなかなか良いのでこれを引用します。

(引用:SteamVR2.5のSteamVR Unity Plugin.pdfより)

このように1.xと2.xでは入力の取得方法がかなり変わっています。通常のフローである旧プラグインを削除して新しいプラグインを追加するやり方だと一気に書き換えないといけませんが、Assembly Definition Fileで区切っていれば順番に実装する事ができます。
…とは言え利用する側は新旧両方を参照する事になるので名前の衝突みたいなものはどうしても発生してしまいます。その場合は新旧実装で名前空間を変えてあとで入れ替える対応をしました。

まとめ

というわけでまとめです。
1.xを削除→2.xを追加では一度に大量のエラーを対処しなくてはならない上それらすべてのエラーをとりのぞいて初めて動作確認ができるようになりますが、Assembly Definition Fileを使ってプロジェクトの中に共存する形にして進めた場合早い段階で動作確認をしながら移行することができました。

SteamVRに限らずあるバージョンアップで大きく変更になる事は稀にあると思います。そういう時に是非今回の話を思い出していただけたらいいなと思います。

おまけ

SteamVRを参照している箇所が多すぎて対応が大変な場合

あきらめて整理しましょう…

SteamVR2.x化で指がうごけるようになったアリシアちゃん

※動画は開発中のものになります