エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

AWS S3のStatic Website HostingでUnity WebGLを配信してみた

ホビーで作っているUnity製ゲーム(WebGL)をEC2ではなく、S3の静的ホスティング機能でどうにかホスティングできないかと試みていたところ、うまく動かせましたので記録を残しておきたいと思います。

動作環境

  • Unity 2020.3.30f1
  • Windows11 Home 21H2(OSビルド 22000.493)

前提条件

WebGLで公開するUnityプロジェクトは既に作成済みとします。

手順

まずはWebGLでビルドする

  • 今回圧縮方法はgzipに指定します
    • Project Settings - Player - Publishing Settings - Compression Formatで圧縮方法を確認できます。

S3バケットを作成

  • 静的ホスティング用のバケットを新規作成します。
  • 「プロパティ - 静的ウェブサイトホスティング」を有効化します。
    • ホスティングタイプ: 静的ウェブサイトをホストするに指定。
    • インデックスドキュメント: index.htmlに指定。
    • エラードキュメント: index.htmlに指定。
  • 「アクセス許可 - ブロックパブリックアクセス」の「パブリックアクセスをすべてブロック」をオフにします。
  • 「アクセス許可 - バケットポリシー」を下記に指定します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{S3バケット名を指定}/*"
        }
    ]
}
  • 「アクセス許可 - Cross-Origin Resource Sharing (CORS)」を下記に指定します。
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]

S3バケットにビルドしたファイルをアップロードする

UnityでWebGLビルドするとindex.html等のファイルが出力されるはずですので、ファイル階層を保ったまま全てS3のルートパスにアップロードします。

S3にアップロードしただけでは動作せずエラーを吐く為、以下のS3のファイルの「メタデータ」を下記の通り変更します。

  • Build/**********.data.gz
    • 「タイプ: システム定義, キー: Content-Encoding, 値: gzip」を追加
  • Build/**********.framework.js.gz
    • 「タイプ: システム定義, キー: Content-Encoding, 値: gzip」を追加
  • Build/**********.wasm.gz
    • 「タイプ: システム定義, キー: Content-Encoding, 値: gzip」を追加
    • 「タイプ: システム定義, キー: Content-Type, 値: application/wasm」に変更

テストプレイする

静的ウェブサイトホスティングバケットウェブサイトエンドポイントへブラウザからアクセスして、うまく動作することを確認します。

うまく動作が確認できたら成功です。お疲れ様でした!

f:id:tansantktk:20220304233022p:plain

EC2で動作させようとするとNginxやApacheといったWebサーバ設定が面倒だったり、そもそも費用がネックだったりするのですが、今回の方法ならその辺の悩みが無くなりそうです😊

なお、今回の静的ウェブサイトホスティングだけではhttpでの配信となる為、実際はCloudFrontをS3の前面に配置してCloudFrontのエンドポイント経由でS3にアクセスさせる構成にしています。

↓別記事に詳細書きました。良ければご覧ください。

tm-progapp.hatenablog.com

おまけ

S3にアップロードしたファイルのメタデータですが、アップロード毎にリセットされてしまうので毎回修正が必要になることに気付きました…これは辛い…🤤

そういうわけでS3にアップロードした後にメタデータを更新するシェルスクリプトを用意して、ビルド後に実行するようにしました。

cd `dirname $0`

aws s3 sync {ローカルのビルドされたファイル群へのパス} s3://{S3バケット名}/

aws s3api copy-object \
--bucket {S3バケット名} \
--copy-source {S3バケット名}/Build/******************.data.gz \
--key Build/******************.data.gz \
--content-encoding "gzip" \
--metadata-directive REPLACE

aws s3api copy-object \
--bucket {S3バケット名} \
--copy-source {S3バケット名}/Build/******************.framework.js.gz \
--key Build/******************.framework.js.gz \
--content-encoding "gzip" \
--metadata-directive REPLACE

aws s3api copy-object \
--bucket {S3バケット名} \
--copy-source {S3バケット名}/Build/******************.wasm.gz \
--key Build/******************.wasm.gz \
--content-encoding "gzip" \
--content-type "application/wasm" \
--metadata-directive REPLACE

AWS CLIではファイルのメタデータのみをピンポイントに更新するコマンドが無いそうなので、s3api copy-objectメタデータを指定して上書きコピーする形になります。

UnityでもCI/CD構築ができるそうなので、GitHub上にソースコードを用意しておいてpushされたら「ビルド+上記のシェルスクリプト実行」をさせることも恐らくできそうです。これはまた時間のある時に試してみようかと思います。