Github Actionsにて自動的にビルドする環境作成(Unity編)

## 結論と概要

[Github Actions](https://github.com/features/actions) を使用してGithubに `git push` が行われたら自動的にUnityビルドを行いその成果物をダウンロードできる仕組みを構築することができたので紹介します。
実際に自動的にUnityビルドを行っているプロジェクトは以下のプロジェクトになります。

[github-actions-examples](https://github.com/TakuKobayashi/github-actions-examples)

こちらのプロジェクトに記載されている内容をコピー、改変して利用してください。
実際に Unityビルドを自動的に行なっている場所(実行している処理のレシピ)は以下のようになります。

[unity-build-personal.yml](https://github.com/TakuKobayashi/github-actions-examples/blob/master/.github/workflows/unity-build-personal.yml)

```yml
name: execute-unity-builds
on:
  push:
    branches:
    - unity-deploy
jobs:
  build:
    name: ${{ matrix.targetPlatform }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        unity-editor-version: [2020.3.26f1]
        unity-license-version: [2020.x]
        node-version: [14.x]
        root-project-path: [Unity]
        targetPlatform:
          - StandaloneOSX # Build a macOS standalone (Intel 64-bit).
          - StandaloneWindows # Build a Windows standalone.
          - StandaloneWindows64 # Build a Windows 64-bit standalone.
          - StandaloneLinux64 # Build a Linux 64-bit standalone.
          - iOS # Build an iOS player.
          - Android # Build an Android .apk standalone app.
          - WebGL # WebGL.
    steps:
      - name: Set up Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

      # Checkout
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      # Cache
      - uses: actions/cache@v3
        id: cache-unity-library
        with:
          key: ${{ runner.os }}-Unity-Library-${{ matrix.targetPlatform }}
          path: |
            ${{ matrix.root-project-path }}/Library
          restore-keys: |
            ${{ runner.os }}-Unity-Library-
      # Cache
      - uses: actions/cache@v3
        id: cache-unity-license
        with:
          key: ${{ runner.os }}-Unity-License-${{ matrix.unity-license-version }}
          path: |
            ${{ matrix.root-project-path }}/Unity_v${{ matrix.unity-license-version }}.ulf
            ${{ matrix.root-project-path }}/Unity_v${{ matrix.unity-editor-version }}.alf
      # Request Unity Activation File
      - name: Request manual activation file
        id: getManualLicenseFile
        uses: game-ci/unity-request-activation-file@v2
        with:
          unityVersion: ${{ matrix.unity-editor-version }}

      # Activate from alf File
      - name: Install node package, `unity-activate`
        run: npm install -g unity-activate
      - name: Activate The License
        id: activateLicense
        run: unity-activate -u "${{ secrets.UNITY_EMAIL }}" -p "${{ secrets.UNITY_PASSWORD }}" -k "${{ secrets.UNITY_AUTHENTICATOR_KEY }}" -o ${{ matrix.root-project-path }}/ "${{ steps.getManualLicenseFile.outputs.filePath }}"
      - name: Read ulf
        id: ulfRead
        uses: juliangruber/read-file-action@v1
        with:
          path: ${{ matrix.root-project-path }}/Unity_v${{ matrix.unity-license-version }}.ulf

      # Build
      - name: Build
        uses: game-ci/unity-builder@v2
        env:
          UNITY_LICENSE: ${{ steps.ulfRead.outputs.content }}
        with:
          targetPlatform: ${{ matrix.targetPlatform }}
          projectPath: ${{ matrix.root-project-path }}
          allowDirtyBuild: true

      # Upload Build
      - name: Upload Build
        uses: actions/upload-artifact@v3
        with:
          name: Build-Results
          path: build/
```

なお

```yml
on:
  push:
    branches:
    - unity-deploy
```

とあるように `unity-deploy` ブランチに`git push`されたタイミングで自動的にUnityのビルドが実行されるようになっています。

実際にUnityビルドを行っているUnityプロジェクトは `Unity/` 以下になります。

[Unity](https://github.com/TakuKobayashi/github-actions-examples/tree/master/Unity)

この `Unity/` 以下のプロジェクトのパスは共通で使用するので以下のように設定しています

```yml
strategy:
  matrix:
    root-project-path: [Unity]
```

Unityビルドが完了した成果物は以下にそれぞれ公開されているのでこちらからダウンロードすることができます。

[Actions/execute-unity-builds](hhttps://github.com/TakuKobayashi/github-actions-examples/actions/workflows/unity-build-personal.yml)

また、[github-actions-examples](https://github.com/TakuKobayashi/github-actions-examples) のプロジェクトではUnityビルドの他にも`Webサイト`、`Android`の自動ビルドについても行なっています。それぞれの自動ビルドの内容についてはこちらにて解説していますので、そちらを参照してください。

* [Github Actionsにて自動的にビルドする環境作成(Android編)](https://qiita.com/taptappun/items/92ec63b7e89e53b68efa)
* [Github Actionsにて自動的にデプロイする環境作成(Webサイト編)](https://qiita.com/taptappun/items/4a8f7ecaa3f91cb21be9)

## Github Actionsとは

通称 [CI(継続的インテグレーション: continuous integration)](https://ja.wikipedia.org/wiki/%E7%B6%99%E7%B6%9A%E7%9A%84%E3%82%A4%E3%83%B3%E3%83%86%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3) / [CD(継続的デリバリー: Continuous Delivery)](https://cloudbees.techmatrix.jp/devops/cd/) が実行できるGithubの機能です。
詳しくは[こちら](https://help.github.com/ja/articles/about-github-actions)を参照してください。

CI/CD実行環境: つまり開発していく中で繰り返し行われる作業を特定のイベントをトリガーにして(今回の場合は `git push` つまりソースコードなどがアップロードされたタイミングで)自動的に記述された処理を実行してくれる環境をCI/CD環境と言います。

## 成果物がダウンロードできるまでの処理の様子

今回、Unityビルドが完了するまでに行われている処理の流れについて、その様子を以下に図示します。

```plantuml
@startuml
actor       Developer
database    Github
database    Unityサーバー
Developer -> Github : git push (Upload)
activate Github
group unity-request-activation-file
  Github -> Unityサーバー : request activationファイル
  Unityサーバー -> Github : alfファイル(activationファイル)をダウンロード
end
group unity-activate
  Github -> Unityサーバー : ログイン(Unityに登録しているアカウントでログイン)
  Unityサーバー -> Github : ログイン完了
  Github -> Unityサーバー : alfファイルをアップロード
  Unityサーバー -> Unityサーバー : alfファイルを元にライセンスを検証
  Unityサーバー -> Github : ulfファイル(ライセンスファイル)をダウンロード
end
group read-file-action
  Github -> Github : ulfファイルを読み込む
end
group unity-builder
  Github -> Github : unityビルド
end
return ビルド完了 + 成果物のダウンロード
@enduml
```

※ 上記の中に登場する各種ファイルについて補足します

* [alfファイル](https://docs.unity3d.com/ja/2018.4/Manual/ManualActivationGuide.html): Unityのライセンス要求ファイル。Unityのライセンスファイルの取得を要求するライセンスファイル
* [ulfファイル](https://docs.unity3d.com/ja/2018.4/Manual/ManualActivationGuide.html): Unity のライセンスファイル。このファイルによってUnityのライセンスを管理しています。

### 補足

上記のUnityの ulfファイル(ライセンスファイル)の取得 を毎回行う必要はないのでキャッシュが使えるのなら一度ダウンロードしたulfファイルをキャッシュに保存して使いまわせるようにした方がいいです。(一応キャッシュを行っている箇所を以下に記述しますが、詳細な解説などは省略します)

```yml
steps:
  # Cache
  - uses: actions/cache@v3
    id: cache-unity-license
    with:
      key: ${{ runner.os }}-Unity-License-${{ matrix.unity-license-version }}
      path: |
            ${{ matrix.root-project-path }}/Unity_v${{ matrix.unity-license-version }}.ulf
            ${{ matrix.root-project-path }}/Unity_v${{ matrix.unity-editor-version }}.alf
```

#### 参考

* [GitHub Actions の Workflow を高速化する](https://qiita.com/qualitia_cdev/items/407b0df9c0a0f0f45bbc)
* [依存関係をキャッシュしてワークフローのスピードを上げる](https://docs.github.com/ja/actions/using-workflows/caching-dependencies-to-speed-up-workflows)

## 使用しているツールについて

### ツール一覧

* [unity-request-activation-file](https://github.com/game-ci/unity-request-activation-file): unityのalfファイルをダウンロードするために使用
* [unity-activate](https://github.com/mob-sakai/unity-activate): ダウンロードしたalfファイルを使ってulf(ライセンスファイル)のダウンロードまで一気にやるために使用
* [read-file-action](https://github.com/juliangruber/read-file-action): ダウンロードしたulfファイルを読み込むために使用
* [unity-builder](https://github.com/game-ci/unity-builder): Unityビルドを行うために使用

### それぞれのツールの使用方法

Unityビルドを自動的に行なっている場所(実行している処理のレシピ)と使用しているツールの解説していきます。

#### [unity-request-activation-file](https://github.com/game-ci/unity-request-activation-file)

```yml
steps:
  - name: Request manual activation file
    id: getManualLicenseFile
    uses: game-ci/unity-request-activation-file@v2
    with:
      unityVersion: ${{ matrix.unity-editor-version }}
```

`${{ matrix.unity-editor-version }}` はビルドするために使用しているUnityのバージョンについて記述しています。ここでは後述する共通で使用する変数として事前に設定している値である `2020.3.26f1` をUnityビルドを行うUnityバージョンとして指定しています。

```yml
strategy:
  matrix:
    unity-editor-version: [2020.3.26f1]
```

↑のように共通で使用する変数として設定しています。この値はビルドしたいUnityのバージョンによってそれぞれ値を変更して利用してください

#### [unity-activate](https://github.com/mob-sakai/unity-activate)

alfファイルをから ulfファイル(ライセンスファイル)を取得する方法は本来は手動で行います。

* [オフライン/ 手動アクティベーション](https://docs.unity3d.com/ja/2018.4/Manual/ManualActivationGuide.html)

本来は手動で行っているものを[Puppeteer](https://developers.google.com/web/tools/puppeteer)を使用して自動的に実行されるようにしています。

* [Unityの.alfファイルから自動で.ulfをダウンロードしたい！](https://qiita.com/MizoTake/items/b85473fab757bb87e4fc)

今回使用しているツールである [unity-activate](https://github.com/mob-sakai/unity-activate) は [Unityの.alfファイルから自動で.ulfをダウンロードしたい！](https://qiita.com/MizoTake/items/b85473fab757bb87e4fc) の記事にて作られたプロジェクトをインスパイアして作られたものになります。
[unity-activate](https://github.com/mob-sakai/unity-activate) は [npm packgae](https://www.npmjs.com/package/unity-activate) であるので使用するためには事前にNPMを使用できる環境を以下のように整える必要があります。

```yml
steps:
  - name: Set up Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v3
    with:
      node-version: ${{ matrix.node-version }}
  - name: Install node package, `unity-activate`
    run: npm install -g unity-activate
```

`${{ matrix.node-version }}` では [Node.js](https://nodejs.org/ja/) のバージョンを指定しています。ここでは `14.x`(14系)を指定しています。

```yml
strategy:
  matrix:
    node-version: [14.x]
```

[unity-activate](https://github.com/mob-sakai/unity-activate) を使用する際には基本的には `unity-activate [alfファイルのパス]` を指定して実行すればいいいのですが、途中でUnityへのログインが必要になるのでそれぞれ実行に必要な引数を指定して実行する必要があります。

1. `-u "[Unityアカウントにログインするためのメールアドレス]"`
2. `-p "[Unityアカウントにログインするためのパスワード]"`
3. `-k "[二段階認証鍵]"`
4. `-o "[ulfファイルの出力先]"`

実行に必要な引数を指定して実行している様子が以下のようになります

```yml
steps:
  - name: Activate The License
    id: activateLicense
    run: unity-activate -u "${{ secrets.UNITY_EMAIL }}" -p "${{ secrets.UNITY_PASSWORD }}" -k "${{ secrets.UNITY_AUTHENTICATOR_KEY }}" -o ${{ matrix.root-project-path }}/ "${{ steps.getManualLicenseFile.outputs.filePath }}"
```

`${{ secrets.UNITY_EMAIL }}` のメールアドレス、`${{ secrets.UNITY_PASSWORD }}` のパスワード、`${{ secrets.UNITY_AUTHENTICATOR_KEY }}` の2段階認証鍵はいずれも秘匿にすべき情報なので機密情報として登録しています。2段階認証鍵については後述します。秘匿情報を設定する方法いついては以下を参照してください。

* [暗号化されたシークレット](https://docs.github.com/ja/actions/security-guides/encrypted-secrets)
* [Github Actionsにて自動的にデプロイする環境作成(Webサイト編)#Github Actionsにて非公開にしたい変数を登録して使用する](https://qiita.com/taptappun/items/4a8f7ecaa3f91cb21be9#github-actions%E3%81%AB%E3%81%A6%E9%9D%9E%E5%85%AC%E9%96%8B%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84%E5%A4%89%E6%95%B0%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%97%E3%81%A6%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B)

`${{ matrix.root-project-path }}` は上記で設定したUnityプロジェクトのパスの値になります。
`${{ steps.getManualLicenseFile.outputs.filePath }}` は [unity-request-activation-file](#unity-request-activation-file) にてダウンロードしたalfファイルのファイルパスを指定しています。`${{ steps.getManualLicenseFile.outputs.filePath }}` は以下のルールにそった値の変数が代入されるように指定しています。

1. `${{ }}` で囲まれたものの中に変数を代入
2. `${{ }}` の中の変数は `steps.[id名].outputs.filePath` のような形式
3. `steps.` は[GitHub Actionsのワークフロー構文](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions)の中の [jobs.<job_id>.steps](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions) に相当するもの
4. `[id名]` は上記 [unity-request-activation-file](#unity-request-activation-file) の `id: getManualLicenseFile` の部分の値
5. `.output.filePath` を指定することでダウンロードしてきたファイルのパスの結果を参照できます

#### [read-file-action](https://github.com/juliangruber/read-file-action)

```yml
steps:
  - name: Read ulf
    id: ulfRead
    uses: juliangruber/read-file-action@v1
    with:
      path: ${{ matrix.root-project-path }}/Unity_v${{ matrix.unity-license-version }}.ulf
```

ulfファイル(Unity のライセンスファイル)の中身はテキストファイルなので、後述する [unity-builder](https://github.com/game-ci/unity-builder) にてUnityビルドを行うためにはulfファイルの中身を読み込む必要があります。ここではそのテキストファイルの中身を読みこんでいます。このようにファイルの値を読み込んで以降の処理に値を参照させるために使用しているものが [read-file-action](https://github.com/juliangruber/read-file-action) になります。
`${{ matrix.root-project-path }}` は上記で設定したUnityプロジェクトのパスの値になります。
`Unity_v${{ matrix.unity-license-version }}.ulf` はダウンロードしてきたulfファイルのファイル名になります。ulfファイルはそれぞれUnityのバージョンに対応したライセンスのファイル名となりここではその値を `${{ matrix.unity-license-version }}` に指定しています。ここではUnityの`2020系` のUnityバージョンを使ってビルドしていますので、ライセンスファイル名として `2020.x` という名前になります。

```yml
strategy:
  matrix:
    unity-license-version: [2020.x]
```

#### [unity-builder](https://github.com/game-ci/unity-builder)

```yml
steps:
  - name: Build
    uses: game-ci/unity-builder@v2
    env:
      UNITY_LICENSE: ${{ steps.ulfRead.outputs.content }}
    with:
      targetPlatform: ${{ matrix.targetPlatform }}
      projectPath: ${{ matrix.root-project-path }}
      allowDirtyBuild: true
```

`UNITY_LICENSE: ${{ steps.ulfRead.outputs.content }}` ではulfファイル(ライセンスファイル)の中身の値を代入しています。ulfファイル(ライセンスファイル)の読み込みは [read-file-action](#read-file-action) にて行った処理の結果を取得しています。
これは [unity-builder](https://github.com/game-ci/unity-builder) でUnityビルドを行うためには必要な情報となります。
`${{ steps.ulfRead.outputs.content }}` は以下のルールにそった値の変数が代入されるように指定しています。

1. `${{ }}` で囲まれたものの中に変数を代入
2. `${{ }}` の中の変数は `steps.[id名].outputs.content` のような形式
3. `steps.` は[GitHub Actionsのワークフロー構文](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions)の中の [jobs.<job_id>.steps](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions) に相当するもの
4. `[id名]` は上記  [read-file-action](https://github.com/juliangruber/read-file-action) の `id: ulfRead` の部分の値
5. `.output.content` を指定することでファイルを読み込んだ結果を参照できます

`targetPlatform: ${{ matrix.targetPlatform }}` ではビルド対象のプラットフォームを指定しています。ここでは `StandaloneOSX`, `StandaloneWindows`, `StandaloneWindows64`, `StandaloneLinux64`, `iOS`, `Android`, `WebGL` の環境をそれぞれビルド対象として指定して行っています。

```yml
strategy:
  matrix:
    targetPlatform:
      - StandaloneOSX # Build a macOS standalone (Intel 64-bit).
      - StandaloneWindows # Build a Windows standalone.
      - StandaloneWindows64 # Build a Windows 64-bit standalone.
      - StandaloneLinux64 # Build a Linux 64-bit standalone.
      - iOS # Build an iOS player.
      - Android # Build an Android .apk standalone app.
      - WebGL # WebGL.
```

その他のビルド可能なプラットフォームの対応状況については以下の通りです。[unity-actions#build](https://github.com/game-ci/unity-actions#build)

| Target Platform             | Done | Status |
|-------------------------|------|--------|
| [WebGL](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml) |
| [Windows Mono](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml) |
| [Linux Mono](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml) |
| [macOS Mono](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml) |
| [Windows IL2CPP](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions status](https://github.com/game-ci/unity-builder/actions/workflows/windows-build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder#windows) |
| [Linux IL2CPP](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions status](https://github.com/game-ci/unity-builder/workflows/Builds/badge.svg?event=push&branch=main)](https://github.com/game-ci/unity-builder#linux) |
| [macOS IL2CPP](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/mac-build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/mac-build-tests.yml) |
| [Android](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml) |
| [iOS](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/build-tests.yml) |
| [Universal Windows Platform](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/windows-build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/windows-build-tests.yml) |
| [AppleTV](https://github.com/marketplace/actions/unity-builder) | ✔ | [![Actions Status](https://github.com/game-ci/unity-builder/actions/workflows/windows-build-tests.yml/badge.svg?branch=main)](https://github.com/game-ci/unity-builder/actions/workflows/windows-build-tests.yml) |
| [Windows Dedicated Server](https://github.com/marketplace/actions/unity-builder) | ❌ | In progress |
| [Linux Dedicated Server](https://github.com/marketplace/actions/unity-builder) | ❌ | In progress |
| [macOS Dedicated Server](https://github.com/marketplace/actions/unity-builder) | ❌ | In progress |
| [Lumin](https://github.com/marketplace/actions/unity-builder) | ❌ | In progress |
| [Xbox](https://github.com/marketplace/actions/unity-builder) | ❌ | Requires license |
| [Playstation](https://github.com/marketplace/actions/unity-builder) | ❌ | Requires license |
| [Switch](https://github.com/marketplace/actions/unity-builder) | ❌ | Requires license |

`projectPath: ${{ matrix.root-project-path }}` は上記で設定したUnityプロジェクトのパスの値になります。

`allowDirtyBuild: true` ではダーティビルドを許可する設定です。(設定の詳細は不明ですがこれを有効にしないとなぜかエラーが出ることがあるので設定しています)

## その他導入、実装までの留意事項やTips

### Unityアカウントの2段階認証について

ulfファイル(Unityライセンスファイル)のダウンロードを行なっている部分が以下の部分になります)

```yml
steps:
  - name: Activate The License
    id: activateLicense
    run: unity-activate -u "${{ secrets.UNITY_EMAIL }}" -p "${{ secrets.UNITY_PASSWORD }}" -k "${{ secrets.UNITY_AUTHENTICATOR_KEY }}" -o ${{ matrix.root-project-path }}/ "${{ steps.getManualLicenseFile.outputs.filePath }}"
```

ここで `secrets.UNITY_EMAIL` と `secrets.UNITY_PASSWORD` はUnityのアカウントにログインするためにUnityにて登録したメールアドレスとパスワードを入力してください。(ここでは`Secret` という形で秘匿しています)
`secrets.UNITY_AUTHENTICATOR_KEY` が2段階認証を設定しているときの鍵の情報になります。
以降にてこの値を確認する方法を紹介していきます。

1. Unityの設定ページ https://id.unity.com/en/settings/tfa/new にアクセスして `Start setup` を選択します

![Unity Start setup.png](https://user-images.githubusercontent.com/12690315/133873890-7bdeb10d-2bde-497b-83e0-2c3586e526ad.png)

2. `Authenticator App` を選択して `Next` を選択します

![Authenticator App.png](https://user-images.githubusercontent.com/12690315/133873893-e1894f2b-67d3-4b7a-877f-70c9613cba24.png)

3. QRコード下の `Can't scan the barcode?` を選択すると `3.In "Enter your key" type the following key (space not required)` の下の部分に文字列が出現します

![AuthenticatorKey.png](https://user-images.githubusercontent.com/12690315/133878441-19553b38-3bd5-492f-a27a-6974923b4add.png)

4. この出てきた文字列を `secrets.UNITY_AUTHENTICATOR_KEY` に設定する

これにより2段階認証が有効になっていてもulfファイルのダウンロードが可能となります。

また2段階認証が有効になっていないままulfファイルのダウンロードを行おうとすると、<font color="#FF0000">途中でメール認証のためのメールが送られてしまい、ulfファイルをダウンロードすることができない</font> というようなことが発生する可能性があります。
そのため2段階認証を用いた上記の方法にて実現することをお勧めします。

### Unityビルド完了後もう一回ビルドする必要があるものについて

今回のUnityビルドはあくまでUnity側で行われるビルドまでを行います。環境によっては実行ファイルを抽出するためには専用の環境でもう一回ビルドする必要があるものもあります。
以下にビルドした成果物を展開した様子になります

![unity-build-result1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72596/4cf783e5-5196-6a5b-ce76-9994f1b2ac8b.png)

![unity-build-result2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72596/66443bb3-eea1-eec7-0320-9018a578df2f.png)

展開したものの様子より、もう一度ビルドする必要がある環境、およびビルドする方法は

* iOS: Xcode を使ってMac OSにて再度ビルド

となります。

### Unity Proライセンスを用いてのUnityビルドについて

[unity-activate](https://github.com/mob-sakai/unity-activate) を使用するときに UnityのProライセンスのシリアルコードを `--serial シリアル番号` または `-s シリアル番号` と指定することでUnityのProライセンスでもUnityの認証を通ってulfファイルをダウンロードすることができます。
例えば以下のようにシリアル番号を設定して [unity-activate](https://github.com/mob-sakai/unity-activate) を実行してください

```yml
steps:
  - name: Activate The License
    id: activateLicense
    run: unity-activate -u "${{ secrets.UNITY_EMAIL }}" -p "${{ secrets.UNITY_PASSWORD }}" -k "${{ secrets.UNITY_AUTHENTICATOR_KEY }}" -o ${{ matrix.root-project-path }}/ -s ${{ secrets.UNITY_SERIAL }} "${{ steps.getManualLicenseFile.outputs.filePath }}"
```

`secrets.UNITY_SERIAL` とあるようにUnityのシリアル番号も非公開にすべき情報なので、Github Actionsの`Secret` に設定するようにしてください
またUnityのライセンスのシリアル番号を確認する場合は以下の方法で確認することができます

1. [Unity ID](https://id.unity.com/) にサインインします。
2. マイアカウントをクリックします。
![unityid_mypage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72596/20cef77b-1233-02fb-39ae-3353589488e7.png)
3. シートをクリックします。
![unity_myseat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72596/0a90b5e6-cc39-eb51-7e4a-e4f92e686cd3.png)

管理しているUnityのアカウントを選択し、Proライセンスのものにのみシリアル番号を確認します。(画像ではProアカウントがないので一覧には出てきていないのですが)

## 参考

実装にあたり参考になった記事を以下に紹介します。

* [UnityとGitHubActionsを使って自動ビルドする【複数プラットフォーム同時ビルド】](https://qiita.com/makihiro_dev/items/03208a83d4c3a1fb426b)
* [game-ci](https://game.ci/docs/)

## まとめ

今回紹介した [Github Actions](https://github.com/features/actions) を使用して自動的にUnityビルドを行う方法、また実際に動くレシピ [unity-build-personal.yml](https://github.com/TakuKobayashi/github-actions-examples/blob/master/.github/workflows/unity-build-personal.yml) を紹介しました。
他にもやり方を紹介している記事などを多くみたのですが
`git push` 〜 Unityビルド完了までを一気に自動的に実現させてくれている記事がなかったため記事を作成しました。
今回紹介したものを活用すると、開発スピードが非常に向上するようになります。
是非活用してみてください。