📦

[VRChat] VPM パッケージ, リポジトリを作ってみた (備忘録)

2024/09/11に公開

はじめに

この記事を読んでる人は VRChat のことも VCC のことも分かってると思うので説明は省略します
備忘録なのでこれだけ読んでやるのはちょっとしんどいかも

フレンドに頼まれて Unity のエディタ拡張を書いたのでそれを VPM パッケージにしていきます
これは単一パッケージで 1 リポジトリとして配信します

内容に誤りが含まれている可能性がありますが筆者は一切の責任を負いません

1 パッケージ化

Converting Assets to a VPM Package に大体書いてあります
Package Maker Tool で大体やってくれるらしいので使ってみたんですが別の Unity プロジェクトで作業しないといけないわりに大したことはしてなさそうだったので手動でやった方がいいんじゃないかと思います
なので手動でやる手順を書きます

以下を行います
ほぼ Changes Needed に書いてある通りなので詳細はそちらを参照してください

  1. パッケージ名 (フォルダ名) を com.example.package-name のように変更する
  2. Editor と Runtime に分離する
  3. package manifest を用意する (§1.1 package manifest)
  4. ハードコードされた Assets/YourPackageName のようなパスを書き換える (cf. Converting Asset Paths)
  5. Assembly Definition ファイルを用意する (1 のパッケージ名に準拠; 詳細は割愛)
  6. GitHub の CI を書く (§1.2 GitHub CI)

4 のパス書き換えはちゃんとやるなら GUID とかで指定するのがいいと思いますが雑に対応するなら Assets/Packages/ にするでもよいです
このとき 1 でパスが変わったらその通りに変更する必要があるので注意が必要です

最終的にこんな感じになると思います (今回はエディタ拡張なので Runtime ディレクトリはないです)

Packages/
+-package.json
`-Editor/
  +-Source1.cs
  +-Source2.cs
  `-com.example.package-name.asmdef

1.1 package manifest

手順 3 の package manifest を用意するところを詳細に書きます
Package Format に詳細が書いてあるんですが読みたくないと思うのでだいたいこれさえ書いとけば OK ってのを書いておきます (Package Maker Tool が出してきたもの)

"author" 欄は最低限名前だけ書いておけば後は別にいいと思います

"unity" は最低 Unity Version です
"2022" にしてもいいですし "2022.3.22" としてもよいです
optional なはずなのでなくても問題ないと思います

{
  "name": "com.example.package-name",
  "displayName": "Example Package",
  "description": "Your package description"
  "version": "1.0.0",
  "gitDependencies": {},
  "vpmDependencies": {},
  "author": {
    "name": "Your Name",
    "email": "your-email@example.com",
    "url": "https://example.com/"
  },
  "legacyFolders": {},
  "legacyFiles": {},
  "unity": "2022.3"
}

この記事を書いてる途中に日本語の有益情報が生えたので載せておきます
【開発者向け】自作物をVPM・VCC対応する方法

1.2 GitHub CI

いい感じにします
基本的には VRChat 公式の CI をベースにファイルを Cloudflare R2 に投げてリポジトリの json を Cloudflare Workers で生成する形式を取っています

VRChat 公式の CI は Unity プロジェクト全体を 1 つのパッケージのために GitHub に上げるのに対して筆者の場合はパッケージのみを GitHub に上げています

以下のような yaml ファイルを .github/workflows に置きます

release.yml
release.yml
name: Build Release

on:
  workflow_dispatch:

jobs:

  # Validate Repository Configuration
  config:
    runs-on: ubuntu-latest
    outputs:
      config_package: ${{ steps.config_package.outputs.configPackage }}
    steps:

    # Ensure that required repository variable has been created for the Package
    - name: Validate Package Config
      id: config_package
      run: |
        if [ "${{ vars.PACKAGE_NAME }}" != "" ]; then
          echo "configPackage=true" >> $GITHUB_OUTPUT;
        else
          echo "configPackage=false" >> $GITHUB_OUTPUT;
        fi

  # Build and release the Package
  # If the repository is not configured properly, this job will be skipped
  build:
    needs: config
    runs-on: ubuntu-latest
    permissions:
      contents: write
    env:
      packagePath: .
    if: needs.config.outputs.config_package == 'true'
    steps:

      # Checkout Local Repository
      - name: Checkout
        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac

      # Get the Package version based on the package.json file
      - name: Get Version
        id: version
        uses: zoexx/github-action-json-file-properties@b9f36ce6ee6fe2680cd3c32b2c62e22eade7e590
        with: 
            file_path: "${{ env.packagePath }}/package.json"
            prop_path: "version"

      # Configure the Environment Variables needed for releasing the Package
      - name: Set Environment Variables
        run: |
          echo "zipFile=${{ vars.PACKAGE_NAME }}-${{ steps.version.outputs.value }}".zip >> $GITHUB_ENV
          echo "unityPackage=${{ vars.PACKAGE_NAME }}-${{ steps.version.outputs.value }}.unitypackage" >> $GITHUB_ENV
          echo "version=${{ steps.version.outputs.value }}" >> $GITHUB_ENV

      # Zip the Package for release
      - name: Create Package Zip
        working-directory: "${{ env.packagePath }}"
        run: zip -r "${{ github.workspace }}/${{ env.zipFile }}" .

      # Build a list of .meta files for future use
      - name: Track Package Meta Files
        run: find "${{ env.packagePath }}/" -name \*.meta >> metaList

      # Make a UnityPackage version of the Package for release
      - name: Create UnityPackage
        uses: pCYSl5EDgo/create-unitypackage@cfcd3cf0391a5ef1306342794866a9897c32af0b
        with:
          package-path: ${{ env.unityPackage }}
          include-files: metaList

      # Make a release tag of the version from the package.json file 
      - name: Create Tag
        id: tag_version
        uses: rickstaa/action-create-tag@88dbf7ff6fe2405f8e8f6c6fdfd78829bc631f83
        with:
          tag: "${{ env.version }}"

      # Publish the Release to GitHub
      - name: Make Release
        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844
        with:
          files: |
            ${{ env.zipFile }}
            ${{ env.unityPackage }}
            ${{ env.packagePath }}/package.json
          tag_name: ${{ env.version }}

      # Move files to upload to Cloudflare R2
      - name: Move files
        run: |
          mkdir ${{ env.version }}
          mv \
            ${{ env.zipFile }} \
            ${{ env.unityPackage }} \
            ${{ env.packagePath }}/package.json \
            ${{ env.version }}

      # Upload files to Cloudflare R2
      - uses: ryand56/r2-upload-action@latest
        with:
          r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
          r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
          r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          r2-bucket: ${{ vars.R2_BUCKET }}
          source-dir: ${{ env.version }}
          destination-dir: ${{ secrets.VPM_REPOSITORY_NAME }}/${{vars.PACKAGE_NAME}}/${{ env.version }}

      # Generate repository json
      - name: Generate repository json
        run: curl "https://vpm-ci-worker.kobi32768.workers.dev"

最後に curl してる Cloudflare Workers の URL は各自のものに変えてください
使用したソースはこれ (自分用にハードコードされた URL と bucket 名が含まれます)
https://github.com/kobi32768/vpm-ci-worker

push するとリポジトリ画面上部の Actions から手動実行できるようになるはず
package.jsonversion を読み取ってタグを打ってビルド, 配信まで自動でやってくれます

GitHub Actions がだいたい全部やってくれるのでこれでほぼ完成と言っても過言ではない

R2 のディレクトリ構造はこんな感じになります

vpm (bucket)
`- repository-A
   +- repository_base.json
   +- vpm.json
   `- package-1
      +- 0.1.0
      |  +- package-1-0.1.0.unitypackage
      |  +- package-1-0.1.0.zip
      |  `- package.json
      `- 1.0.0
         +- package-1-1.0.0.unitypackage
         +- package-1-1.0.0.zip
         `- package.json

2 配信

R2 は独自ドメインにバインドして https://vpm.example.com/vpm.json のように直接ファイルにアクセスできるようにできます
なので vcc://vpm/addRepo?url=https://vpm.example.com/vpm.json のようにしてブラウザで読み込むと VCC (ALCOM) からインストールできるようになります

参考文献

Discussion