PackageManagerで自作ライブラリを作成する方法  

Unity2018.3あたりからPackageManagerがかなり使いやすくなったので、ライブラリの作り方と公開方法をまとめてみました。

PackageManagerって何だという人は以下の参考になるブログ記事を見てください。

参考ブログ
http://tsubakit1.hateblo.jp/entry/2018/08/16/221016
https://note.mu/fuqunaga/n/ne331cb5600fe
https://synamon.hatenablog.com/entry/2018/05/26/165332

## はじめに

これまでのPackageManagerはUnity公式以外のサードパーティーがライブラリを作成したり公開するには不便でしたが、以下のアップデートのおかげでかなり実用的になりました。

* GitHubのURL指定でPackageを導入できる
* 相対パスで指定したフォルダにあるPackageを導入できる
* ProjectViewのPackageフォルダから内容を見る/編集できる

この記事では新しいPackageManagerを使うことで、自作パッケージを簡単に作成して公開する方法を紹介します。

## 使ってみる
公式のPackageに関してはUnityEditorにあるPackageManager Windowを使うことで好きなPackageをインストールできました。
![packagemanager-ui.PNG](https://qiita-image-store.s3.amazonaws.com/0/361356/d2601bc3-cbe4-b23d-53bc-be66d8de5756.png)

このUIで設定すると、Packageフォルダ内にあるmanifest.jsonファイルの内容が変更されます。
Unityはこの設定ファイルを見てどのパッケージを利用するかを管理しています。

```manifest.json
{
  "dependencies": {
    "com.unity.ads": "2.3.1",
    "com.unity.analytics": "3.2.2",
    "com.unity.assetbundlebrowser": "1.5.0",
        [中略]
  },
}
```

このような形でパッケージ名とバージョンを指定しているのですが、PackageManager Windowを使わないで手動で書き換えることができます。(詳細な書き方が知りたい人は公式のマニュアルを参照)
https://docs.unity3d.com/Packages/com.unity.package-manager-ui@1.8/manual/index.html#PackManManifestsPackage

### URL指定でPackageを導入する
manifest.jsonのdependenciesの中に、以下のように
`[package名] : [GitHubのURL], `
のような形で追記することで、GitHubにあるパッケージを直接ダウンロードして簡単に導入することができます。

```manifest.json
{
  "dependencies": {
        [中略]
    "com.unity.ads": "2.3.1",
    "jp.ickx.common": "https://github.com/ProjectICKX/UnityCommon.git",
        [中略]
  },
}
```

* GitHubのリポジトリのルートに設定ファイルpackage.jsonが必要
* プライベートリポジトリからは不可

という制約はあるものの、書くだけでダウンロードからインストールまで自動で行ってくれます。

### 指定したフォルダにあるPackageを導入する
PCの任意のフォルダにあるPackegeもインストールすることができます。
`[package名] : [file:./Packageフォルダからの相対パス],`

```manifest.json
{
  "dependencies": {
        [中略]
    "com.unity.ads": "2.3.1",
    "jp.ickx.common": "file:../../UnityCommon",
        [中略]
  },
}
```

このように書けば、

```フォルダ構成
├─UnityCommon 
│      package.json
│
└─Project
    ├─Assets
    ├─Packages
    │     manifest.json
    └─ProjectSettings
```

のようなフォルダの階層の相対位置にあるUnityCommonフォルダのPackageを導入するという意味になります。

PackageManager Windowにも「＋」ボタンを押してpackage.jsonを選択すれば同様のことが可能ですが、その場合は絶対パスになってしまい、manifest.jsonをバージョン管理しても他の人が使えなくなってしまうので相対パスに修正するといいと思います。

### ProjectViewで内容を見る
昔はAssetsフォルダ以下のファイルしか閲覧できませんでしたが、Unity2017.2ぐらいからPackageを閲覧できるようになりました。
ダウンロードしたPackageは`Library\PackageCache`フォルダに保存されいるのですが、そのフォルダ構成とファイルが普通のアセットのように見ることができます。(例はPackages内のTextMesh Pro)
![package_view.PNG](https://qiita-image-store.s3.amazonaws.com/0/361356/5098247d-a466-10db-7118-8e3e7a0f9c6c.png)

Unity公式のアセットは見るだけで編集できないのですが（むしろ読み取り専用にする方法を知りたい）、実は前述のフォルダを指定したPackageに関しては編集することができます。

**アセットを作成することもできれば、MaterialなどのInspectorのパラメータを編集することすらできます。**
このUnityの仕様変更のおかげで自作パッケージの作成が格段に楽になりました。

## 作ってみる

実際に新しくなったPackageManagerの仕組みを生かして自作パッケージを作って管理してみたいと思います。

####1 **パッケージを開発するためのプロジェクトを作成する**

これはUnityで新しいプロジェクトを作成してもいいですし、既存のプロジェクトをそのまま使ってもいいでしょう。

####2 **任意の名前でGitHubでリポジトリを作成してチェックアウトする**

公開前提のパッケージならGitHubでリポジトリを作って、開発用プロジェクトと同じフォルダにチェックアウトします。
非公開なら任意の名前でフォルダを作ったり、プライベートリポジトリにしてしまえばいいでしょう。

```
├─HogePackage          <-- 自作Package
│
└─HogePackage_Develop  <-- 開発用プロジェクト
    ├─Assets
    ├─Packages
    └─ProjectSettings
```

パッケージ名をHogePackageとしてフォルダ構成がどのようになっているかを示します。
今回は開発用プロジェクトとpackageフォルダを同じ階層に配置しました。

####3 **2で作成したリポジトリのルートフォルダにpackage.jsonを作成する**
テキストファイルを作成し、名前をpackage.jsonにします。

```package.json
{
    "name": "com.unity.hoge-package", <-- com.[開発者名].[パッケージ名] のように書く模様(小文字のみ「-」「.」は使える
    "displayName": "HogePackage",     <-- 任意のパッケージ名
    "version": "1.0.0",               <-- パッケージのバージョン
    "unity": "2018.1",                <-- Unityのバージョン
    "description": "説明分",
    "dependencies": {                 <-- 依存するパッケージ… だが今は自動で解決してインストールはできないらしい
        "com.unity.package-1": "1.0.0",
    }
}
```
このファイルはリポジトリのルートフォルダに置く必要があります。 

####4 **開発用プロジェクトのmanifest.jsonに相対パスで作ったpackageを登録する**
チェックアウトしたフォルダを相対パスで指定します。

```
├─HogePackage          <-- 自作Package
│      package.json
│
└─HogePackage_Develop  <-- 開発用プロジェクト
    ├─Assets
    ├─Packages
    │     manifest.json
    └─ProjectSettings
```

このようなフォルダ構成ならPackagesフォルダの2階層上にHogePackageがあるので以下のように指定します。

```manifest.json
{
  "dependencies": {
        [中略]
    "com.unity.ads": "2.3.1",
    "com.unity.hoge-package": "file:../../HogePackage",
        [中略]
  },
}
```

####5 **Assembly Definition Filesを作成する**
ソースコードを含める場合、Assembly Definition Filesを適切に設定しておくことで、ほかのPackageから参照して使えるようになります。
Runtime / Editor / TestでDefinitionを分けるとベストです。

```
├─HogePackage
│  │  package.json
│  └─Scripts
│      ├─Editor
│      │      Unity.HogePackage.Editor.asmdef
│      ├─Runtime
│      │      Unity.HogePackage.Runtime.asmdef
│      └─Test
│             Unity.HogePackage.Test.asmdef
```

例えば現在作っているパッケージでは、Editorフォルダ内のスクリプトからRuntimeフォルダ内のスクリプトを使う必要がありますが、Referenceの設定を使ってEditorのDefinitionからRuntimeのDefinitionに対して参照を設定すれば問題ありませんでした。また、いろいろなパッケージから使う予定の便利なコードを集めたCommonパッケージを用意しているのですが、そのRuntimeのDefinitionを参照に登録すれば、別のパッケージのスクリプトを呼び出すこともできました。

![def.PNG](https://qiita-image-store.s3.amazonaws.com/0/361356/ed28fcd1-43a7-8335-c292-0d818dfece69.png)

(Assembly Definition Filesについては以下のブログを参考に)
http://tsubakit1.hateblo.jp/entry/2018/01/18/212834

####6. **開発用プロジェクトからパッケージを編集して開発する**
相対パスでフォルダを登録しているので、Pakcagesフォルダの中も自由にアセットを追加したり編集できます。
ソースコードやアセットの追加も右クリックのメニューにある「Create」から行えますし、Assetsフォルダ以下で作業するのとほとんど変わらずに開発ができるはずです。

![packageassetcreate.PNG](https://qiita-image-store.s3.amazonaws.com/0/361356/99b2ace0-8830-a82f-81e0-37aa4edd67fd.png)

ただし、公開を想定している場合はパッケージ内のアセットを書き換えるような処理を書いたり、ユーザーに編集してもらうような想定のアセットを用意するのはよくありません。本来PackageManagerで管理するパッケージは一般的にバージョン管理対象にしないLibraryフォルダ以下にダウンロードされるので、他の人とチーム開発する場合に変更が反映されないからです。

もし編集してほしいアセットを含めたいのであれば、テンプレートとしてAssetsフォルダにコピーしてもらったり、コピーや生成処理をするようなEditor拡張をしたほうがいいでしょう。

Packageに含めないけど動作確認に使いたいアセットは、開発用のUnityプロジェクトのAssetsフォルダに作ればOKです。
Assetsフォルダ側のアセットから、Package側のアセットを参照することはできるので困ることはないでしょう。

####7. **完成したらGitHubにアップロードする**

HogePackageはリポジトリからチェックアウトしたフォルダなので、そのままコミットしてmasterにマージをするなどすれば公開できます。
GitHubならReadmeに導入方法やマニュアルを書いておけば、このリポジトリを知った人がすぐに使うことができるはずです。

開発用プロジェクトを残しておけば、バージョンアップや修正も対応しやすいかと思います。

####8. **使いたい別のProjectのmanifest.jsonにURLを使って登録する**

Packageを使うだけのひとであればURLでpackageをダウンロードしてもらえばいいので、manifestに1行書いてもらうだけでインストールできます。

```manifest.json
{
  "dependencies": {
        [中略]
    "com.unity.ads": "2.3.1",
    "com.unity.hoge-package": "https://github.com/Hoge/HogePackage",
        [中略]
  },
}
```

# WindowsでSourceTreeを使っている人向け

UnityのPackageManagerでGitHubからダウンロードする場合、Gitがコマンドラインから利用できる必要があります。
以下の記事を参考にすれば、SourceTreeに入っているGitをコマンドラインで使えるようになります。
http://www.it-tech-box.com/2016/05/sourcetree-git-cmd/

#まとめ

無料公開するPackageならこの手順で簡単に作成して公開できます。

非公開のライブラリだとmanifest.jsonにURLを書いてインストールすることができないので、
**同じ相対パスになるようにチーム全員で非公開のリポジトリをチェックアウト**してもらい、manifest.jsonに相対パスでPackageをインストールさせればいいかと思います。

ProjectViewでPackagesフォルダが表示されたり、相対パスでPackageをインストールできる前は、PackageManagerに対応するソースコード以外のアセットが含まれるpackageを開発するのは難しいものでした。**今回の修正でマテリアルやテクスチャ、プレハブなどのアセットを使うようなパッケージも作りやすくなりました。**


今後はAsset StoreもPackageManagerで利用できる形で提供されると非常にうれしいですね。

# 最後に

この方法でAudioコンポーネントの録音ライブラリを作ってみました。
https://github.com/alternator/AudioRecorder
manifest.jsonに以下の一文を追加すればインストールできます

```
"jp.ickx.audiorecorder": "https://github.com/alternator/AudioRecorder.git",
```

## 追記

今回の管理法は結構簡易的なものなので、本気で管理するならもんりぃ先生さんの記事を参考にするといいかもしれません。
https://monry.hatenablog.com/entry/2019/04/17/024205
https://monry.hatenablog.com/entry/2019/06/11/161455