ゲームジャム作品のランキング機能をニフクラ mobile backendからAWSに移行しました

[UdonTech Advent Calendar 2023](https://qiita.com/advent-calendar/2023/udontech)の20日目です。

[2024年3月にサービス終了することになったニフクラ mobile backend](https://mbaas.nifcloud.com/info/2023/11/post-171.html)（以下NCMB）からAWS（API Gateway + Lambda + DynamoDB）へゲームジャム作品のランキング機能を引っ越ししましたので内容を紹介します。

# 移行対象のゲームについて

[「商店街ゲームジャム」](https://sanuki-gamen.connpass.com/event/289885/)という約1ヶ月間のゲームジャムで作られた「三びきのコブタ ―サンドイッチは世界を救う―」というシューティングゲームです。unityroomで遊べます。

unityroom:

https://unityroom.com/games/shotengaigamejam2023teamd0902

ソース:

https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902

このゲームのランキング機能にNCMB（データストア + NCMB Unity SDK）を使っていたので、AWSのAPI Gateway + Lambda + DynamoDBへ移行しました。

## ランキング画面

ランキング画面は以下の感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952672/74ccb42e-cbf6-55d6-ec39-d24297330c16.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952672/ed6587a5-4042-5679-f310-c9cd40bcd1b5.png)

内容としては、

1. ゲームクリア後にランキング取得 + 表示
1. プレーヤー名入力後にスコア送信

という感じの画面です。

## 移行前・移行後のソース

- [ランキング取得部分のソース（NCMB版）](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/88de49605ee2c00330b5240a9dd2e3ffe9c01675/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L212-L221)
    - [移行後のソース](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/main/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L216C1-L224)
- [スコア送信部分のソース（NCMB版）](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/88de49605ee2c00330b5240a9dd2e3ffe9c01675/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L358-L375)
    - [移行後のソース](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/main/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L385-L422)
    - [バックエンド側（Lambda）の実装](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/main/Server~/SanbutaShooting/src/SanbutaShooting/Function.cs)

NCMB版のランキング機能は以下の記事の実装を参考に作成しました。

https://blog.naichilab.com/entry/webgl-simple-ranking

# AWS以外の移行先について

NCMBの[サービス終了告知ページ](https://mbaas.nifcloud.com/info/2023/11/post-171.html)に

> なお、本サービスの終了に伴い他社類似サービスのご案内を予定しております。
> こちらは内容確定でき次第改めてご連絡させていただきます。

とあるので、近いうちに公式が良い感じの移行先を案内してくれそうです。  （12/25追記 [案内記事来てました](https://blog.mbaas.nifcloud.com/entry/2023/12/20/135133)）

AWS以外に以下の移行先も検討しましたが、今回はAWSの勉強がしたかったのでAWSを選びました。

- [Google Cloud Firebase](https://firebase.google.com/?hl=ja)
- [Cloudflare Workers + KV](https://www.cloudflare.com/ja-jp/developer-platform/workers/)
- [Unity Leaderboards](https://unity.com/ja/products/leaderboards)

# 移行手順

移行手順を簡単にまとめます。

## API Gateway + Lambda + DynamoDBをセットアップする

以下の記事を参考にバックエンド側をセットアップしました。

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-dynamo-db.html

上記の記事では関数の言語にNode.jsを使う形で解説されていますが、今回はUnityと言語を合わせたかったのでC#で関数を書くことにしました。ただ、C#だとマネジメントコンソール上で関数を編集することができなくて、ローカルでプロジェクトをセットアップしてdotnetコマンドを使って関数をアップロードする必要があってやや面倒でした。

C#での関数の作成・デプロイは以下の記事が参考になりました。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/csharp-package-cli.html

- [関数のソース（再掲）](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/main/Server~/SanbutaShooting/src/SanbutaShooting/Function.cs)

DynamoDBのテーブルの項目は以下の感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952672/a2f485d3-c8a0-395e-3f30-2b48ac39a2d2.png)

API GatewayはOPTIONSとANYを作ってCORSの設定をして[（参考）](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-cors-console.html)、ANYは「入力パススルー: テンプレートが定義されていない場合 (推奨)」を設定した感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952672/971fc76c-10ed-413d-4ff4-c2492a17e3ed.png)


## NCMB管理画面からランキングデータをエクスポートする

NCMB管理画面にログインし、対象のアプリページを開いて右上の「アプリ設定」からアプリ設定画面を開き、エクポートタブからエクスポートを行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952672/7d65c04f-350b-7a90-76dd-30407493c6d5.png)

## ランキングデータをDynamoDBにインポートする

エクスポートしたランキングデータ（JSON）を手元で良い感じのCSVに変換してDynamoDBにインポートしました。[（参考）](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/S3DataImport.Format.html)

## ゲームのランキング取得処理・スコア送信処理を変更する

NCMBのUnity SDKを使ってNCMBデータストアにアクセスする形から、UnityWebRequestを使ってAPI Gatewayにアクセスする形に変更しました。

- [変更内容のコミット](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/commit/aec2929ba898acb26cc6c78a2d5519b0d9f1aceb)
    - ランキング取得部分のソース（再掲）: [NCMB版](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/88de49605ee2c00330b5240a9dd2e3ffe9c01675/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L212-L221)・[移行後版](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/main/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L216C1-L224)
    - スコア送信部分のソース（再掲）: [NCMB版](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/88de49605ee2c00330b5240a9dd2e3ffe9c01675/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L358-L375)・[移行後版](https://github.com/k-mitani/ShotengaiGameJam2023TeamDPrototype0902/blob/main/Assets/k-mitani/StageClear/StageClearSceneManager.cs#L385-L422)

## unityroomへアップロード、移行完了

問題なく動くことを確認してunityroomへアップロードしました。

移行は以上で完了です。

# 移行してみて

ランキング取得処理もスコア送信処理もNCMB版よりややレスポンスが遅くなりました。

特にDynamoDBはオンデマンドモードで動かしているので、久しぶりのアクセスだとレスポンスが返ってくるまで3.5秒ぐらいかかるようになりました（NCMB版より2秒ぐらい遅くなりました。LambdaのInit Durationは200msぐらいです）。ランニングコスト0なのでまあいいかと思っています。

次ランキング機能を作る機会があれば、Unity Leaderboardsを使ってみようかなと思います。

以上です。