白黒羊

PlayFabのC#向けSDKをUnityで使用してAsyncAwaitする(with GitHubActions)

前置き

PlayFabのSDKはC#向けのものが2種類あります。

片方はUnity用、片方はUnity以外のC#用です。
Unity用のものはunitypackageが用意されている他、PlayFab Unity Editor Extensions を使えばUnityEditorから更新することができます。
が、Unity用のSDKには非同期メソッドがありません。コールバック地獄になってしまいます。
どうしてもasync awaitしたかったので、Unity以外用SDKを使うことにしました。
このSDKはWebGLでは使えないので注意です。iOS、Androidでは問題なく使えました。

Unity用ではないので、当然unitypackageもEditor拡張もありません。
GitHubのレポジトリがあるので、 git clone してから自分のプロジェクトにコピペしてあげればもちろん使えますが、それなりに頻繁に更新されるSDKのため、それをいちいちやるのも手間です。
できれば他のpackageと同じようにUnity Package Manager(UPM)で管理できると嬉しいですね。

そこで、次の手順でUPMで管理できるようにしてみます。

  1. GitHubのリポジトリをFork
  2. package.jsonを作成する
  3. UnityのProject内にリポジトリのデータを移して各ファイルに.metaファイルを作成する
  4. Assets/ フォルダを作成して、ほしいデータをしまう
  5. GitHub Actionsを用いて、更新されたときに自動的にアップデートするようにする
  6. GitHubにpushする

GitHubのリポジトリをFork

C# PlayFab SDK をforkして、そのデータをローカルにcloneします。

package.jsonを作成する

UPMで扱えるようにpackage.jsonを作ります。
PlayFabSDK/source/package.jsonとしておきます。
今回はどこかに登録することは考えておらず、自分用に作るだけなので、内容は割と適当です。

{
  "name": "studio.shirokurohitsuji.playfab",
  "version": "1.91.210406",
  "displayName": "PlayFab",
  "description": "SDK for C#/.net environments.",
  "unity": "2020.3",
  "unityRelease": "0f1",
  "keywords": [
    "PlayFab",
    "CsharpSdk"
  ],
  "author": {
    "name": "Shirokurohitsuji",
    "url": "https://github.com/shirokurohitsuji"
  }
}

最小構成では nameversion があれば良いみたいです。本当はnameの値はcomから始めないといけないみたい。

【参考】 https://docs.unity3d.com/2020.3/Documentation/Manual/upm-manifestPkg.html

Unityのプロジェクト内にリポジトリのデータを移して各ファイルに.metaファイルを作成する

.metaファイルが存在しないデータはUnityPackageManager経由でダウンロードできません。一度Unityのプロジェクトの中にcloneしたデータを移して.metaファイルを作る必要があります。

この図はPlayFabSDKのディレクトリ階層図ですが、必要になるのは基本的にPlayFabSDK/source下のファイルたちだけなので、sourceフォルダをUnityProjectにドラッグ&ドロップしましょう。
それぞれのファイルに.metaファイルができたらそれをコピーしてcloneしたディレクトリに貼り付けます。

Assets/ フォルダを作成して、ほしいデータをしまう

Unity用のパッケージにするには.metaファイルを作成する以外に、Assetsフォルダも必要になようです。
Assets/PlayFabSDK/… となるように一番上の階層にAssetsフォルダを作って、PlayFabSDKフォルダだけが含まれるようにします。

GitHub Actionsを用いて、更新されたときに自動的にアップデートするようにする

.github/workflows/auto_merge.yml を作成します。

# Follow Changes of Forked/Upstream Repository.
#
# This workflow rebase-marge changes from upstream's master to origin's master. 
# - Ref:
#   - https://stackoverflow.com/a/61574295/12102603 by N1ngu @ StackOverflow (EN)
#   - https://qiita.com/KEINOS/items/3bcaa6cea853f6b63475 by KEINOS @ Qiita (JA)

name: sync_playfab

# Triggers the action as scheduled
on:
  # Runs on 0:00 everyday
  schedule:
    # Ref: 
    #   - https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule
    #   - https://crontab.guru/examples.html
    # Cron format:
    #         ┌───────────── minute (0 - 59)
    #         │ ┌───────────── hour (0 - 23)
    #         │ │ ┌───────────── day of the month (1 - 31)
    #         │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
    #         │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
    #         │ │ │ │ │                                   
    #         │ │ │ │ │
    #         │ │ │ │ │
    #         * * * * *
    - cron:  '0 0 */1 * *'
  push:
    branches:
      - master

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Merge upstream
        run: |
          git config --global user.name ${NAME}
          git config --global user.email ${EMAIL}
          # Pass the --rebase-merges option to git rebase by default
          git config --global pull.rebase merges
          # "git checkout master" is unnecessary, already here by default
          git pull --unshallow  # this option is very important, you would get
                                # complains about unrelated histories without it.
                                # (but actions/checkout@v2 can also be instructed
                                # to fetch all git depth right from the start)
          # Add the repo which you forked to the remote and name it as "upstream"
          git remote add upstream ${REPO_FORK}
          # Fetch the upstream branches to local
          git fetch upstream
          # Merge changes
          git checkout master
          git merge --no-edit upstream/master
        env:
          NAME: shirokurohitsuji
          EMAIL: shimahinuko@shirokurohitsuji.studio
          REPO_FORK: https://github.com/PlayFab/CSharpSDK.git

      - name: Count changes
        id: changes
        run: |
          git add -N .
          echo "::set-output name=count::$(git diff upstream/master --name-only | wc -l)"
      - name: Get Version
        if: steps.changes.outputs.count > 0
        id: regex-match
        shell: bash
        run: |
          VERSION=`cat Assets/PlayFabSDK/source/PlayFabSDK.csproj | sed -n 's/\s*<Version>\(\S*\)<\/Version>$/\1/p'`
          echo "::set-output name=version::$VERSION"
      - name: Find and Replace
        if: steps.changes.outputs.count > 0
        id: replace
        uses: jacobtomlinson/gha-find-replace@master
        with:
          find: '\d\.\d{2}\.\d{6}'
          replace: ${{ steps.regex-match.outputs.version }}
          include: "Assets/PlayFabSDK/source/package.json"

      - name: Update repository
        if: steps.replace.outputs.modifiedFiles > 0
        run: |
          git add -A
          git commit -m ":arrow_up: update version ${{ steps.regex-match.outputs.version }}"
          git push origin master

【参考】 https://qiita.com/KEINOS/items/3bcaa6cea853f6b63475

1日1回、もしくはmasterにpushしたときにこのjobが走ります。
0:00と書いてありますが、タイムゾーンは UTC(GMT) なので日本時間で決まった時間に動かしたい場合は必要に応じて調整してください。
変更がなければ途中で中止、変更があればmergeしてバージョン名を取得してpackage.jsonを書き換え、pushする自動化ができます。

GitHubにpushする

ステージング、コミットをしてmasterブランチにプッシュするとGitHubActionsが走ります。現時点では変更が無いはずなので途中でスキップされてしまいますが、本家リポジトリに更新があったときに自動的にSyncしてバージョンを更新してくれます。

今回の手法で作成したリポジトリです。
shirokurohitsuji_CSharpSDK_ SDK for C#_.net environments for Unity

CSharpSDKをUPMで使いたいという場合はUPMのGit URLに https://github.com/shirokurohitsuji/CSharpSDK.git?path=Assets/PlayFabSDK/source#master を指定してあげれば使えます。