既存ライブラリを Unity Package Manager で導入できるようにする

みなさんこんにちは。ryohey です。最近弊社でアウトプットを強化しようという話があったので、早速やったことを備忘録として書いてみました。

概要

弊社は AR で教科書を拡張するアプリ A-txt を小山高専と共同開発しています。A-txt のソース管理を Unity Collaborate から GitHub へ移行した際に、リポジトリサイズ削減のために AR 用のライブラリ artoolkitX を Unity Package Manager (以下 UPM) に対応し、別リポジトリで管理しました。本記事では、既存の Asset を UPM に対応する方法を説明します。

完成したパッケージはこちら ryohey/arunityx に公開しています。

手順

  1. パッケージ用のディレクトリを用意
  2. package.json を追加
  3. 開発用プロジェクトを作成
  4. 開発用プロジェクトにローカルの依存を追加
  5. パッケージにアセンブリ定義を追加
  6. 依存をリモートリポジトリに変更

1. パッケージ用のディレクトリを用意

元が Asset の場合は適当なディレクトリに Asset の中身を配置します。リポジトリがある場合は fork して clone します。ディレクトリ内にはパッケージ利用側に必要なファイルだけがあればよいので、Unity プロジェクトになってなくてもよいです。ディレクトリ構成の例はこちらの公式ドキュメントを参考にして下さい。

2. package.json を追加

NPM と同様に、パッケージのメタデータを package.json によって定義します。パッケージのディレクトリ構成によって package.json の配置場所が変わります。

ルートに配置する例

ルートに Scripts などがある場合はルートに package.json を追加します。

- Scripts
- Plugins
- Materials
- Resources
- package.json

ルート以外に配置する例

UPM で使いたいアセットが深い階層にある場合は、使いたいアセットがある階層に package.json を配置します。例えば Assets ディレクトリ以下だけを使いたい場合は Assets ディレクトリ内に package.json を配置します。

- Assets
  - Scripts
  - Plugins
  - Materials
  - Resources
  - package.json

package.json

package.json は下記のように記述します。

{
  "name": "com.covelline.arunityx",
  "displayName": "artoolkitX for Unity3D",
  "version": "1.0.2",
  "unity": "2019.4",
  "description": "UPM fork of arunityx",
  "dependencies": {
  }
}

3. 開発用プロジェクトを作成

package.json を追加すればパッケージとして認識されるようになりますが、このままでは .meta ファイルが無い警告が出ることや、アセンブリ定義を作成する必要があるため、開発用のプロジェクトが必要となります。

空のプロジェクトをパッケージが対応するバージョンの Unity で新規作成します。この後の手順はこのプロジェクトを開いた状態で行うことができます。

4. 開発用プロジェクトにローカルの依存を追加

プロジェクトの Packages/manifest.json を下記のように編集しローカルのパッケージを追加します。ファイルパスは相対パスで package.json があるディレクトリを指すように記述します。

git で入れたパッケージの場合は Unity Editor 上から書き込み出来ない状態になるため、ここではローカルのディレクトリを参照するように指定します。

"dependencies": {
  "com.covelline.arunityx": "file:../../arunityx/",
  ...
}

5. パッケージにアセンブリ定義を追加

パッケージにアセンブリ定義がないとスクリプトを参照することができないので、ない場合は作成します。

開発用プロジェクトからは Project タブから Packages にてパッケージの編集を行うことができます。

f:id:ryoheyc:20200721182107p:plain

パッケージのスクリプトがあるディレクトリ内にアセンブリ定義 (asmdef ファイル) がない場合は、こちらから作成します。Editor 用と Runtime 用のスクリプトがある場合はそれぞれのアセンブリ定義を作成します。

6. 依存をリモートリポジトリに変更

開発用プロジェクトからパッケージのスクリプト等を利用できるか確認し、問題がなければいよいよ共有できるようにします。 パッケージを GitHub 等に push し、manifest.json をローカルの参照から git リポジトリを参照するように変更します。この時、# を使ってハッシュを指定しておくと、パッケージの中身を変更したときに tag などを打つ必要が無いため、また向き先が明らかなため開発しやすいです。正式なリリースのときにはバージョン番号で tag を打って指定するとよいでしょう。

"dependencies": {
  "com.covelline.arunityx": "https://bitbucket.org/ryohey/arunityx.git#2063a5d",
  ...
}

package.json がルートにない場合は path クエリで次のように指定します。

"dependencies": {
  "com.covelline.arunityx": "https://bitbucket.org/ryohey/arunityx.git?path=/Assets#2063a5d",
  ...
}

所感

以上でアセットを UPM 経由で導入できるようになりました。リポジトリもスッキリして、サードパーティのライブラリも編集できなくなるのでこれで安心して作業が進められます。

補足1

subtree を使って、特定のディレクトリがルートになるようにブランチを切ることもできるようですが、今回試したところ Git LFS で管理されているファイルが正常に入らなかったため見送りました。

補足2

導入したパッケージは Library/PackageCache に入っているため、この中身を直接編集してパッケージの修正などを行うこともできます。しかし、git で追跡できないことや、新規作成したファイルの .meta ファイルが生成されないなど不便な点もあるため、file: でローカルディレクトリを参照して開発するのがよいでしょう。