url: https://www.hanachiru-blog.com/entry/2023/10/23/120000
title: "【Unity】Unity Package Manager(UPM)が認識する自作Packageを作成し、git経由でインストールできるまで整える - はなちるのマイノート"
description: "はじめに 今回は自作パッケージを作成しPackageManagerのAdd package from git URLからインストールできるようにする手法について紹介したいと思います。 実際にインストールしている様子 はじめに カスタムパッケージの作成 ファイル・フォルダを生成する 中身を記述する package.json [company-name].[package-name].asmdef [company-name].[package-name].Editor.asmdef Package Managerから確認する Add package from git URLからインストールできる…"
host: www.hanachiru-blog.com
favicon: https://www.hanachiru-blog.com/icon/link
image: https://cdn.image.st-hatena.com/image/scale/5296831d2d0d0a1c41b632fa4f23ca8b4ad64986/backend=imagemagick;version=1;width=1300/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2Fh%2Fhanaaaaaachiru%2F20231022%2F20231022002307.png

事前知識

Unity Package Manager について調べる

はじめに

おしごとで Unity をつかっていくうえで、 便利な自社ライブラリをつかって git 経由で配布するということが多いです。 今回は実際に簡単なライブラリをつくってみて、他プロジェクトから使ってみる、ということをおこないます。

Add(x, y) ライブラリを含んだプロジェクトを作成する

Add(x, y) という計算をするだけのスクリプトを含んだライブラリを作成し、それを配布できるようにしていきます。

UnitySample_Adder というプロジェクトを新たに作成し、 GitHub へ公開します。 ただの空 Scene しかないプロジェクトです。

https://github.com/ganyariya/UnitySample_Adder/tree/568385142dd9abd205a3ecef79747701fced1fa3

Imgur

なにも設定していない上記の空 UnityProject から下記のパッケージのためのレイアウトを作っていきます。

url: https://docs.unity3d.com/ja/2021.3/Manual/cus-layout.html
title: "パッケージレイアウト - Unity マニュアル"
description: "カスタムパッケージに推奨するパッケージレイアウトです。"
host: docs.unity3d.com
favicon: ../StaticFiles/images/favicons/favicon.png
image: https://unity3d.com/files/images/ogimg.jpg

[YourUnityProject]/Packages/[YourPackage] = <root> となります。

<root>
  ├── package.json
  ├── README.md
  ├── CHANGELOG.md
  ├── LICENSE.md
  ├── Third Party Notices.md
  ├── Editor
   ├── [company-name].[package-name].Editor.asmdef
   └── EditorExample.cs
  ├── Runtime
   ├── [company-name].[package-name].asmdef
   └── RuntimeExample.cs
  ├── Tests
   ├── Editor
   ├── [company-name].[package-name].Editor.Tests.asmdef
   └── EditorExampleTest.cs
   └── Runtime
        ├── [company-name].[package-name].Tests.asmdef
        └── RuntimeExampleTest.cs
  ├── Samples~
        ├── SampleFolder1
        ├── SampleFolder2
        └── ...
  └── Documentation~
       └── [package-name].md

今回は下記のようなプロジェクト構成を目指します。

UnitySample_Adder/Packages/com.ganyariya.adderpackage
  ├── package.json
  ├── README.md
  ├── Editor
   ├── com.ganyariya.adderpackage.Editor.asmdef
   └── EditorExample.cs
  ├── Runtime
   ├── com.ganyariya.adderpackage.asmdef
   └── RuntimeExample.cs
  ├── Tests
   └── Runtime
        ├── com.ganyariya.adderpackage.Tests.asmdef
        └── RuntimeExampleTest.cs
  ├── Samples~
        ├── SampleFolder1
        ├── SampleFolder2
        └── ...

Editor は Unity エディタ上でのみ有効にしたいもの、つまり Unity 開発を手助けする拡張機能のコードを入れます。 Assemb Definition を作成する際も Editor である、つまり Publish Build したときに含まれないようにする設定をおこないます。

一方、Runtime は Publish Build したときに含まれる、実機に含まれるコードになります。 Editor/Runtime を分けることで良い設計になる、かつ実機のバイナリサイズが小さくなります。

Tests にはユニットテストを、Samples にはユーザがテストできるようなサンプルシーンを用意します。

package.json を作成する

UnitySample_Adder/Packages 配下に手動でディレクトリを作成し、かつ package.json を手動で作成します。 下記のように package.json を記入しました。

UnitySample_Adder/Packages/com.ganyariya.adderpackage on main [?] is 📦 v1.0.0 via  v22.14.0 [☁️ ]
 cat package.json -p
{
    "name": "com.ganyariya.adderpackage",
    "displayName": "SampleAdder",
    "version": "1.0.0",
    "unity": "2022.3",
    "description": "Unity Learn. Only Add Package.",
    "keywords": [],
    "license": "MIT",
    "category": "",
    "dependencies": {}
}

この状態で Unity を開くと SampleAdder という Package が表示されました。 package というファイルを開くと、インスペクタ上で package.json の値が確認できます。

Imgur

Assembly Definition を作成する

url: https://docs.unity3d.com/ja/2018.4/Manual/ScriptCompilationAssemblyDefinitionFiles.html
title: "スクリプトのコンパイルとアセンブリ定義ファイル - Unity マニュアル"
description: "Unity は、スクリプトがどのようにマネージアセンブリにコンパイルされるかを自動的に定義します。 通常、スクリプトの変更に対する Unity エディターのコンパイル時間は、プロジェクトに加えるスクリプト量が増えるほど長くなります。"
host: docs.unity3d.com
favicon: ../StaticFiles/images/favicons/favicon.png
image: https://docs.unity3d.com/ja/2018.4/uploads/Main/ScriptCompilation.png

Unity 上で Runtime というディレクトリを作成します。 その後 Runtime ディレクトリ上で Assembly Definition を作成します。 com.ganyariya.adderpackage.asmdef の設定はなにも変更せずデフォルトのままとしました。

Imgur Imgur Imgur

同様に Editor ディレクトリを作成し、 asmdef ファイルを作成します。 Editor の asmdef ファイルは下記の変更を加えています。

  • Assembly Definition References に com.ganyariya.adderpackage を指定している
    • Runtime で実装した機能を Editor で利用するため
  • Platforms を Editor のみにする
    • Editor 配下で実装したものは Unity 開発中でしか有効にしない
      • Publish Build では含めたくないため

Imgur

ここまでおこなうと SampleAdder というパッケージが Package Manager 上で確認できます。 Imgur

https://github.com/ganyariya/UnitySample_Adder/pull/1

Runtime 配下に C# スクリプトを書く & テストを実装する

Add するだけのスクリプトを Runtime/Adder.cs として実装しました。 Imgur

namespace Ganyariya.SampleAdder
{
    public class Adder
    {
        public int Add(int x, int y)
        {
            return x + y;
        }
    }
}

続いてテストできるようにしていきます。 SampleAdder/Tests/Runtime を手動で作成します。

Imgur

SampleAdder/Tests/Runtime へ com.ganyariya.adderpackage.Tests.asmdef を作成します。 そして、下記のように設定することで Adder クラスに対するユニットテストを実装できるようにします。

  • Assembly Definition References を設定する
    • UnityEditor.TestRunner
    • UnityEngine.TestRunner
      • UnitTest を実行するために必要
    • com.ganyariya.adder.package
      • SampleAdder.Adder を参照するために必要
  • Platforms を Editor に設定する

Imgur

最後に SampleAdder/Tests/Runtime へ AdderTest.cs を作成しユニットテストを実装します。

using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
 
namespace Ganyariya.SampleAdder.Tests
{
    public class AdderTest
    {
        [TestCase(1, 2, 3)]
        [TestCase(-1, 2, 1)]
        [TestCase(0, 0, 0)]
        public void AdderAddTest(int x, int y, int expected)
        {
            var adder = new Adder();
            var actual = adder.Add(x, y);
            Assert.AreEqual(expected, actual, $"x: {x}, y: {y}");
        }
    }
}

Test Runner でテストが通れば SampleAdder Package 内において、正しく Adder が Test から参照できている ことがわかります。

Imgur

Editor 配下に C# スクリプトを書く

本来 Editor 配下には Unity 上での開発を便利にする拡張機能などを実装します。 ただし、今回はあくまでも仕組みの理解のため簡単な意味のないコードを書きます。

シーンを再生したときに ganyariya.adderpackage をインストールしてますよ〜 というメッセージを Console に出すだけのスクリプトです。 RuntimeInitializeOnLoadMethod という Attribute を利用しています。

Imgur

using UnityEngine;
 
namespace Ganyariya.SampleAdder
{
    public static class EditorAdderConfirmer
    {
        [RuntimeInitializeOnLoadMethod]
        public static void ConfirmFeature()
        {
            Debug.Log("あなたは ganyariya.adderpackage をインストールしています");
 
            var adder = new Adder();
            const int x = 10;
            const int y = 20;
            
            Debug.Log($"x = {x} + y = {y} の結果は {adder.Add(x, y)}です。 これは adderpackage の Adder クラスで計算できます。");
        }
    }
}

空プロジェクトをつくったときに作成されたデフォルト Scene を再生すると、このメッセージが正しく表示されることがわかります。

Imgur

ここまでの内容のコミットが以下です。

https://github.com/ganyariya/UnitySample_Adder/commit/b771e10b31104c0ed5261e0de190fec01ae89f36

サンプルシーンを用意する

ライブラリ利用者向けのためにサンプルシーンを用意します。

Samples フォルダを作成し、 com.ganyariya.adderpackage.sample という asmdef を作成します。 設定内容は画像のとおりです。 注意すべき点として、Platform を Any Platform としています。

実は最初 Editor のみにしていたのですが、 後述する AdderConsoleLogger を GameObject へアタッチできませんでした。候補からそもそもでてこなかったのです。 これは 実行時 (Runtime) 時に MonoBehaviour がアタッチされる仕組みであり、 Editor のものは表示されない、ということが考えられます。 よって Any Platform に変更しています。

Imgur

using Ganyariya.SampleAdder;
using UnityEngine;
 
 
namespace Ganyariya.SampleAdder.Sample
{
    public class AdderConsoleLogger : MonoBehaviour
    {
        [SerializeField] private int x;
        [SerializeField] private int y;
 
        void Start()
        {
            var adder = new Adder();
            var result = adder.Add(x, y);
 
            Debug.Log($"x = {x}, y = {y}, addResult = {result} in AdderConsoleLogger");
        }
    }
}

上記の AdderConsoleLogger を AdderConsoleLoggerGameObject へアタッチし AdderSampleScene を実行したところ、正しくログが表示されました。 このように Samples 配下へテストシーンを用意することで、どのようにライブラリを使うのか?を説明できそうです。

Imgur

https://github.com/ganyariya/UnitySample_Adder/pull/2

SampleAdder パッケージを別プロジェクトから git 経由で利用する

それではさきほどまで開発した SampleAdder パッケージを別プロジェクト UnitrySample_AdderUser から利用することとします。

Imgur

空プロジェクトとして作成したコミットは以下です。

https://github.com/ganyariya/UnitySample_AdderUser/tree/d9ebb716e9b54c744d00ad431e5c5bf13eb1afb6

SamplePackage を UTM 経由でインポートする

UnityPackageManager を利用して SamplePackage を UnitySample_AdderUser へインポートします。

Imgur

UnityPackageManager へ GitHub への URL で追加するときのレファレンスは下記が参考になります。

url: https://orotiyamatano.hatenablog.com/entry/2023/05/30/%E3%80%90%E5%82%99%E5%BF%98%E9%8C%B2%E3%80%91%28Unity%29git%E3%81%8B%E3%82%89PackageManager%E3%81%B8%E3%81%AE%E8%BF%BD%E5%8A%A0%E6%96%B9%E6%B3%95
title: "【備忘録】(Unity)gitからPackageManagerへの追加方法 - YAMADA TAISHI’s diary"
description: "こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。 Unityへパッケージを追加する時、GitURLで追加することがあります。 度々書き方を忘れるので備忘録用に記事化します。 目次 GitURLによる追加する意義 基本ルール GitのURLまたはSSHでの接続URLの指定 pakcage.jsonが格納してあるフォルダまでのパス指定 合わせるとこんな感じ プライベートリポジトリへのアクセス ブランチへのアクセス tagの指定 参考 まとめ GitURLによる追加する意義 パッケージは直接UnityPackageなどでも追加出来るが、Git…"
host: orotiyamatano.hatenablog.com
favicon: https://orotiyamatano.hatenablog.com/icon/link
image: https://cdn.image.st-hatena.com/image/scale/e45408a26de917805542ee7ccda04f0fd4b8cc87/backend=imagemagick;version=1;width=1300/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2FO%2FOrotiYamatano%2F20230530%2F20230530122027.png

今回のケースでは

ことから、入力すべき git URL は以下になります。

https://github.com/ganyariya/UnitySample_Adder.git?path=/Packages/com.ganyariya.adderpackage

Imgur

インストールが完了すると SampleAdder が正しく表示されています。 うれしいですね。

Imgur

インストールした Package の情報は UnitySample_AdderUser の Packages/manifest.json に追加されていました。 Packages/manifest.json ファイルにおいて、インストール情報は管理されるようです。

UnitySample_AdderUser/Packages on  feature/import-sampleadder-from-utm [!] [☁️ ] took 18s
❯ cat manifest.json -p
{
  "dependencies": {
    "com.ganyariya.adderpackage": "https://github.com/ganyariya/UnitySample_Adder.git?path=/Packages/com.ganyariya.adderpackage",
    "com.unity.ai.navigation": "2.0.9",
    "com.unity.collab-proxy": "2.10.0",
    "com.unity.ide.rider": "3.0.38",
    "com.unity.ide.visualstudio": "2.0.25",
    "com.unity.inputsystem": "1.14.2",

SampleAdder パッケージをインポートした PR は以下になります。 https://github.com/ganyariya/UnitySample_AdderUser/pull/1

ちなみに、UnitySample_AdderUser プロジェクト上で Adder.cs を開くと UnitySample_AdderUser/Library/PackageCache というディレクトリに存在しました。

Imgur

複数のプロジェクトをまたいで利用するかつ変更しないものについてはグローバルキャッシュ (mac であれば ~/Library/Unity/cache) に配置されます。 そして、今回のような git url のものは Project/Library/PackageCache へ配置されるようです。

 pwd
/Users/ganyariya/Library/Unity/cache/packages/packages.unity.com
 
cache/packages/packages.unity.com [☁️ ]
 ls
 [email protected] [email protected] [email protected]
 [email protected] [email protected] [email protected]
 [email protected] [email protected] [email protected]
 [email protected] [email protected] [email protected]
 [email protected] [email protected]
 [email protected] [email protected]
UnitySample_AdderUser/Library/PackageCache on main [!] [☁️ ]
 ls
 com.ganyariya.adderpackage@3a23e91f5544 com.unity.render-pipelines.core@04755ad51d99
 com.unity.ai.navigation@5218e4bf7edc com.unity.render-pipelines.universal-config@8dc1aab4af1d
 com.unity.burst@1df634d836b8 com.unity.render-pipelines.universal@bc6f352be672
 com.unity.collab-proxy@1e5e48aff19d com.unity.rendering.light-transport@2c9279f90d7c
 com.unity.collections@aea9d3bd5e19 com.unity.searcher@1e17ce91558d
 com.unity.ext.nunit@031a54704bff com.unity.shadergraph@2c9221ffedf4
 com.unity.ide.rider@1f60b3138684 com.unity.test-framework.performance@0840f58e4562
 com.unity.ide.visualstudio@74aa435fc4bb com.unity.test-framework@d97b7cd61ded
 com.unity.inputsystem@be6c4fd0abf5 com.unity.timeline@6b9e48457ddb
 com.unity.mathematics@8017b507cc74 com.unity.ugui@7056cb05de4c
 com.unity.multiplayer.center@f3fb577b3546 com.unity.visualscripting@b4d700247d4b
 com.unity.nuget.mono-cecil@d78732e851eb
 

UnitySample_AdderUser プロジェクト側で Add メソッドを呼び出す

最後に UnitySample_AdderUser 側で Add メソッドを呼び出します。 UserAdder.cs を作成し、 UserAdderGameObject へアタッチします。

Play した結果正しく result が表示されました。

using Ganyariya.SampleAdder;
using UnityEngine;
 
public class UseAdder : MonoBehaviour
{
    [SerializeField] private int x;
    [SerializeField] private int y;
    
    void Start()
    {
        var adder = new Adder();
        var result = adder.Add(x, y);
        Debug.Log($"use adder package: x={x} + y={y} = {result}");
    }
}

Imgur

https://github.com/ganyariya/UnitySample_AdderUser/pull/2

まとめ

  • UnityPackageManager でインポートできるようなパッケージを作成したい場合 package.json を含むディレクトリを作成する
    • ライブラリ開発用 UnityProject の Packages/[PackageName] でつくるとよい
  • GitHub 経由でインポートする場合は package.json の path を入力する

Packages/[PackageName] のように開発すると、利用者側は https://.....?path=/Packages/[PackageName] のように指定してインポートしないといけず面倒です。 Packages/[PackageName] 配下を submodule として開発し、そのまま配布する、というのも手なのかもしれませんね。