本稿は新歓ブログリレー2024 37日目 の記事になる予定でした。
こんにちは、3時間ほどブログ投稿の時間を逸脱しました。ゲーム班のinutamago_dogeggです。今回は、unityroomというサイトで冬ハッカソンでつくったゲーム『Orbit』を公開する時に苦しんだ話をします。2024年の2月頃(大学は春休み中)の話です。
まず初めに
UnityにはAddressablesという、アセットを管理するパッケージがあります。Resourcesと違う点としては「ゲーム本体と分離してアセットを配信する」という点です。
デフォルトの設定では、ビルドした時にできるStreamingAssets
フォルダーがアセットの置き場になっています。ビルドしたファイルたちを一括で上げて配信するサイト(例えば itch.io )では特にいじらなくて良いと思われます。
いつものファイルたち
しかしUnityroomでは、以下のようにビルドしたファイルを別々でアップロードする形式になっており、かつアセットファイルを上げる項目がありません。
そのため、自前でサーバーを用意して、そこにアセットを上げ、そのサーバーを通してアセットを取得する必要があります。
どうしよう
私はゲーム制作一筋で生きてきた人間で、サーバーについて何も知りません。そのためまずは先人の知恵に頼りました。
- UnityRoomで動かす!Addressables個人的メモ(デプロイ編) #Unity - Qiita
- 【unity】AddressablesとAWSのS3+CloudFrontを使用してサーバからアセットをダウンロードできるようにする その1 - とたぎナレッジブログ
上記記事を参考にして、AWSの S3 とCloudFront を用いることにしました。
S3: サーバーにコンテンツを保持できるやつ
CloudFront: エンドユーザーとサーバーの間を上手く取り持ってくれるやつ
という認識で今回は大丈夫だと思います(自分も詳しくわかりません)。
つまり、S3にアセットをアップロードし、CloudFrontを経由してロードしよう!ということになります。
指示に従ってやっていくぞ
【unity】AddressablesとAWSのS3+CloudFrontを使用してサーバからアセットをダウンロードできるようにする その1 - とたぎナレッジブログ
【unity】AddressablesとAWSのS3+CloudFrontを使用してサーバからアセットをダウンロードできるようにする その2 - とたぎナレッジブログ
以上の記事に従い、
UnityRoomで動かす!Addressables個人的メモ(デプロイ編) #Unity - Qiita
も参考にしながらまずやってみました。詳細は記事に書いてあるので、かいつまんでやったことを書きます。
S3側の設定
- AWSのアカウントをつくった。
- バケットを作成した。
- バケットポリシーはデフォルトで
s3:GetObject
を許可されていました。
- バケットポリシーはデフォルトで
- バケットに
StreamingAssets
の下にあるアセットたちをアップロードした。StreamingAssets/aa
フォルダーをそのまま上げました。
- CORSの設定を書いた
- UnityRoomで動かす!Addressables個人的メモ(デプロイ編) #Unity - Qiitaに書いてあるコードをとりあえずコピペしました。
コピペしたCORS
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
CloudFront側の設定
- 作成したS3バケットをオリジンドメインにしてディストリビューションを作成した。
Unity側の設定
- Addressables ProfilesタブのRemoteの項目で、タイプを
Custom
にし、Remote.LoadPathをCloudFrontのURLにした。- Addressable Profilesのタブは、Unityウィンドウの上部の
Window
からWindow/Asset Management/Addressables/Profiles
と開きました。
- Addressable Profilesのタブは、Unityウィンドウの上部の
- 配信したいAddressables Asset Groupの、Build & Load Pathsの部分をcustomにしようとしたが、Groupのビルドが上手くいかなくなったのでLocalのままにした。
- ビルドフォルダー内の
Build
フォルダーの中にあるhogehoge.loader.js
のstreamingAssetsUrl(2か所)を作成したCloudFrontのディストリビューションドメインに書き換えた。
あれ?
はい、上手く行きませんでした。
具体的には、アセットロードのタイミングで 403 Forbidden エラーを吐いていました。(開発者ツールから見ました。)
404 Not Foundではないため、ロードしようとしたURLはちゃんと存在しているみたいですね。つまり Load Pathの設定はちゃんとできているみたいです。
何が原因?
403エラーと言うことは、そのサーバーにアクセスする権限が無いということです。
今回の話で言うと、Unityroom側から、CloudFront経由で、S3に上げたアセットをロードする、という権限が無いということになります。
このタイミングで今まで指示に従ってきただけなのが足を引っ張ってきます。アクセス制限をかけているような場所の目星が付きませんでした。
そのため、今まで出てきて意味がわからなかった単語の意味をとりあえず知ることにしました。
バケット
S3サービスで使われる用語。S3 に保存されるオブジェクトのコンテナのことを指す。
参考:
ドメイン
IPアドレス(ネットワーク上の住所)につけた名前。
単にドメインと略されていることもある。
例: example.co.jp
, qiita.com
, trap.jp
参考:
オリジン
プロトコル、ドメイン名、ポート番号を合わせたものを言う。
例: http://www.example.co.jp:80
参考:
オリジンドメイン
オリジンドメインは、このオリジンのオブジェクト CloudFront を取得する Amazon S3 バケットまたは HTTP サーバーの DNS ドメイン名です
???
恐らく原文が英語なので変な説明になっています。
配信するコンテンツが置かれているサーバーのドメインを指すのだと思います。
CloudFrontで使われる用語のようです。公式のドキュメントが読みづらい。
参考
- https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesDomainName
- 【初心者必見】Amazon CloudFrontについて|伊藤忠テクノソリューションズ
ディストリビューション
ドメインごとに割り当てられるCloudFrontの設定のこと。
CloudFrontで使われる用語のようです。公式のドキュメントが読みづらい2。
参考:
CORS
Cross-Origin Resource Sharing(オリジン間リソース共有)の略。
別のオリジンにあるリソースへのアクセス権限の設定がこれでできるのだと思います。
参考:
- CORS - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
- オリジン間リソース共有 (CORS) - HTTP | MDN
- CORSについて簡単に説明する | SIOS Tech. Lab
知らない単語を調べた結果、それっぽいものを見つけました。CORSです。
確かに指示に従っている時にちょくちょくCORSという単語を目にした記憶があります。
S3にコピペしてきたCORSの設定が悪かったのでしょうか?
知識が無い状態でいじるのはかなり大変そうです。そこで有識者の先輩を助っ人に呼びました。
すると「むしろ今の設定はアクセス許可を与えすぎているレベルで、この状態でアクセス制限がかかるのは明らかにおかしい」とのことでした。
確かに、AllowedOrigins
, AllowedHeaders
はワイルドカードですし、AllowedMethods
ではDELETEという見るからにヤバそうなメソッドまで許可しています。
つまりは、S3でなくCloudFront側のCORSの問題だと目星を付けました。
(有識者はtraPの先輩である@topazさんと@urturnさんをお呼びしました)
つらい
結論から先に言うと、CloudFrontのビヘイビア設定の中の「オリジンリクエストポリシー」と「レスポンスヘッダーポリシー」を適切に指定できていないのが問題でした。
しかし
当時は公式ドキュメントを見たり、有志のサイトを見たり、ディストリビューションの管理ページを血眼で見たりしても、該当の設定をいじれる場所を見つけることができませんでした。
見つからなさ過ぎて別の箇所に原因があるという確信さえ持ち始めていました。
進展が無いため(有識者の人の助けを借りて)試行錯誤をしました。
具体的に言うと、localhostのサーバーにアセットを上げてロードしてみたり、curlコマンドでS3のリソースに直接リクエストしてみたりなどです。
具体的に何をしたかはけっこう忘れてしまったのですが、見た記事はまとめてあったので列挙しておきます
- https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/troubleshoot-403-errors.html
- https://enakizv.hatenablog.com/entry/2023/02/08/150953
- https://zenn.dev/bun913/articles/cloudfront-cors-policies#cloudfrontのキャッシュポリシーを設定する
- https://repost.aws/ja/knowledge-center/s3-configure-cors#:~:text=てください。-,CORS ルールをテスト,-CORS ルールを
- https://qiita.com/relu/items/3461753e3886072349c7
- https://discussions.unity.com/t/unity-web-request-cors-error-on-webgl-hosted-on-aws-but-works-on-editor/253728#:~:text=in post %232-,I managed to resolve this by using a CORS proxy server to relay the request and it now works like a charm.,-For anyone who
- https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141#43881141
- https://marudice.hatenablog.jp/entry/2022/05/15/151244
初めて403エラーを出したのが18:00頃。そこから夜飯を挟み、最終的には深夜の2:00くらいまでPCと向き合っていました。
最終的にしたこと
翌朝起きてまた活動をし始めました。
改めてCloudFrontの管理画面を見返してみました。
すると以下のことに気付きました。
わかりにくすぎないか。
ですがここまで来たら後はポリシーを設定し直すだけです。
これで正常にアセットがロードされました。
ディストリビューションをつくる時に一緒に適切に設定してしまえば苦労することは無かったと思います。
まとめ
- AWSのUIが不親切過ぎる
- AWS公式ドキュメントには文字しか書いていない。画像情報が無くて本当にわかりづらい。
- 深夜にバグ探しをすべきではない
他にも色々学べたので結果的には良かったです。
苦労してunityroomに上げたゲームは↓から遊べます!!
https://unityroom.com/games/dogegg_orbit
評価とコメントお願いします!!!
新歓ブログリレー今日の担当は@d_etteiu8383さんです。お楽しみに!