GitHub ActionsでUnityのCI環境を構築するときに詰まったこと

# はじめに
GitHub ActionsでUnityのCI環境を構築するときに詰まったことをまとめました。
**成果物は[こちら](#成果物)から**

**構築の全体の流れを知りたい場合は以下の記事が参考になると思います。**
[GameCI で Unity の CI 環境を GitHub Actions で構築する](https://zenn.dev/nikaera/articles/unity-gameci-github-actions)

# 詰まったこと
## projectPathの設定方法
### 問題
UniEyeControllerはUPMでの配布の関係で`(Root)/Assets`ではなく、`(Root)/UniEyeControllerDev~/Assets`という構成となっています。

`matrix.projectPath`を定義しただけでprojectPathを設定した気になっていましたが、
以下のようなエラーが出てCIが通りませんでした。
関連するIssue: [Incorrect project path · Issue #61 · game-ci/unity-actions](https://github.com/game-ci/unity-actions/issues/61)
```
Project settings file not found at "ProjectSettings/ProjectVersion.txt". Have you correctly set the projectPath?
```
``` yml:.github/workflows/build.yml（matrix部分抜粋）
matrix:
  projectPath:
    - UniEyeControllerDev~/
  targetPlatform:
    - StandaloneWindows
    - StandaloneWindows64
    - Android
```

### 方法
unity-builderのprojectPathに`${{ matrix.projectPath }}`を設定することでCIが通るようになりました。
matrixを使わずに直接projectPathに`UniEyeControllerDev~`を指定しても通ります。

``` yml:.github/workflows/build.yml（unity-builder部分抜粋）
- uses: game-ci/unity-builder@v3
  env:
    UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
  with:
    projectPath: ${{ matrix.projectPath }}
    targetPlatform: ${{ matrix.targetPlatform }}
```

## Cache actionの設定方法
### 問題
GitHub Actionsには2回目以降のビルド等を高速化する仕組みとして[Cache action](https://github.com/actions/cache/tree/main)があります。
しかし、path, key, restore-keysがサイトによってまちまちだったため、何を設定すれば良いかが分かりませんでした。

### 方法
[公式のドキュメント](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key)を読むことで理解できました。
* path
どのパスのコンテンツをキャッシュ・復元するかを指定します。
Unityの場合はテクスチャ等のキャッシュが置かれるLibraryフォルダを指定します。

* key
キャッシュを区別するためのキーを指定します。
キーに対応するコンテンツのキャッシュがある場合は、pathにコンテンツを復元します。
キーの設定の方法は色々とありますが、一例として`Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}`と指定した場合は、同一プロジェクトの同一プラットフォームの場合に同一のキャッシュを使用するようになります。
必要に応じて`${{ hashFiles(matrix.projectPath) }}`のように、ファイルのハッシュを追加することもできます。

* restore-keys
復元時にkeyに対応するコンテンツのキャッシュが無かった場合に、キーについて前方一致した最新のキャッシュが復元されます。
完全一致でなくても、なるべく近いキャッシュがあったら流用したいという考えです。
下記の例の場合、上から順番に一致するものが検索されます。
  * `Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}-`
プロジェクトのファイルのハッシュが異なる場合
  * `Library-${{ matrix.projectPath }}-`
ターゲットのプラットフォームが異なる場合
  * `Library-`
プロジェクトが異なる場合

``` yml:.github/workflows/build.yml（actions/cache部分抜粋）
- uses: actions/cache@v3
  with:
    path: ${{ matrix.projectPath }}/Library
    key:
      Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}-${{ hashFiles(matrix.projectPath) }}
    restore-keys: |
      Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}-
      Library-${{ matrix.projectPath }}-
      Library-
```

# 成果物
* リポジトリ
個人で開発しているUnityの視線制御用のアセットである[UniEyeController](https://github.com/mkc1370/UniEyeController)のリポジトリを使用しました。

* build.yml
``` yaml:.github/workflows/build.yml
name: Build project

on: [push, pull_request]

jobs:
  buildForSomePlatforms:
    name: Build for ${{ matrix.targetPlatform }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        projectPath:
          - UniEyeControllerDev~/
        targetPlatform:
          - StandaloneWindows
          - StandaloneWindows64
          - Android
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          lfs: false
      - uses: actions/cache@v3
        with:
          path: ${{ matrix.projectPath }}/Library
          key:
            Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}-${{ hashFiles(matrix.projectPath) }}
          restore-keys: |
            Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}-
            Library-${{ matrix.projectPath }}-
            Library-
      - uses: game-ci/unity-builder@v2
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
        with:
          projectPath: ${{ matrix.projectPath }}
          targetPlatform: ${{ matrix.targetPlatform }}
```