どこに置く?
先日AssetBundleを使う機会がありました。
UnityRoomで利用したかったので外部でホスティングする必要があるのですが、どこに置いたらいいんでしょうか?
GCSとかS3とかでいいんじゃ、と思われるかもしれませんがこれらのストレージサービスは金がかかります。大した金額にはならないと思いますが、なるべく無料の範囲で抑えたいのが人情でしょう。今回はAssetBundle置き場として、無料のストレージサービスやホスティングサービスをいくつか試してみました。
調査対象
Dropbox, GoogleDrive, netlify, github, githubpages
の5つです。
なおこの記事はこれらのサービスでAssetBundleのホスティングが可能であることを保証するものではありません。商用非商用を問わず各サービスの利用規約を読んで自己責任でお願いします。ダメだよとかいけるよとか知っている人はコメントください。
調査方法
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.Networking;
public class DLManager : MonoBehaviour
{
public InputField urlField;
public Text status;
public Text time;
public Text dlSpeed;
bool isDownloading = false;
public void StartDownLoad()
{
if (!isDownloading)
{
StartCoroutine(DLCoroutine());
}
}
IEnumerator DLCoroutine()
{
isDownloading = true;
using (var request = UnityWebRequestAssetBundle.GetAssetBundle(urlField.text))
{
var asyncOpe = request.SendWebRequest();
float startTime = Time.time;
yield return new WaitUntil(() => {
int percentage = (int)(asyncOpe.progress * 100);
status.text = "downloading..." + percentage.ToString() + "%";
return asyncOpe.isDone;
});
if (request.isHttpError || request.isNetworkError)
{
status.text = request.error;
isDownloading = false;
yield break;
}
float finishTime = Time.time;
status.text = "Complete!";
var abHandler = request.downloadHandler as DownloadHandlerAssetBundle;
var assetbundle = abHandler.assetBundle;
float deltaTime = finishTime - startTime;
time.text = string.Format("{0:#.##}", deltaTime) + "[sec]";
}
isDownloading = false;
}
}
こういうものを作りました。InputFieldに打ち込んだURLからAssetBundleをダウンロードし、そのダウンロードにかかった時間を表示するという素敵アプリです。これで各サービスからのDL時間を計測して最速を決定したいと思います。
調査環境
Unity 2019.2.0f1
AssetBundleサイズ:55.6MB
ネット環境
調査1:ローカル実行
僕の当初の目的はWebGLアプリケーションなのですがWebGLとローカル(スタンドアロンとかエディタ上とか)では結果が変わってくるかもしれないのでまずはエディタ上で見ていきたいと思います。
GoogleDrive
ストレージサービスと言えばまずはこれでしょう。ちなみに共有用のリンクを少し書き換える必要があります。こちらの記事を参考にさせて頂きました。
Dropbox
こちらもまたストレージサービスの代名詞ですね。
こちらも共有リンクを少し書き換える必要があります。末尾のdl=0をdl=1にするだけです。
netlify
ウェブ屋さんなら誰でも知ってる話題のホスティングサービスですね。僕はウェブ屋さんじゃないのでつい最近まで知りませんでした。
github
githubpages
あのgithubのホスティングサービスです。期待できそうですね。
結果
サービス名 | 結果[sec] |
---|---|
GoogleDrive | 28.36 |
Dropbox | 77.69 |
netlify | 169.11 |
github | 24.21 |
githubpages | 15.84 |
githubpages, github, GoogleDriveが速いですね。netlifyはちょっと実用には堪えない遅さ。ADSL等のもっと低速な環境では下手をすれば4分ぐらいかかりそうですね。意外なのはgithubよりもgithubpagesの方が速いことです。リポジトリ管理サービスよりもウェブサイトのホスティングの方が速度が求められるからでしょうか?不思議です。 |
調査2:WebGL
大本命のWebGL上での速度を計測していきましょう。Build&Runでローカルサーバを建ててその上で実行していきます。ローカルでダウンロードするのとブラウザからダウンロードするのに違いはあるのでしょうか?
GoogleDrive
Dropbox
netlify
github
githubpages
結果
サービス名 | 結果[sec] |
---|---|
GoogleDrive | 失敗 |
Dropbox | 失敗 |
netlify | 失敗 |
github | 失敗 |
githubpages | 19.72 |
githubpagesを除く全てのサービスで失敗してしまいました。一体どうしたことでしょう。 |
その名もCORS
F12を押してエラーメッセージを見てみましょう。
ウェブを触ったことある人なら見たことあるのではないでしょうか。僕はウェブを触ったことが無いので初めて見ました。
これはCORSという「異なるドメイン間でのリソースの共有」に関する仕組みに起因するエラーです。UnityはWebGLアプリケーションでAssetBundleをロードする際"XmlHttpRequest"という形でサーバにリクエストを送ります。この際WebGLアプリが動作しているドメイン(つまりブラウザで開いているページのドメイン)とAssetBundleが置いてあるドメインが同一の場合は何も問題はありません。(実際に上の実験ではnetlifyもCORSではじかれていますがnetlifyにアプリをデプロイすると読み込めるようになります。)
しかし二者のドメインが異なる場合はセキュリティ上の問題が発生します。そこで定められたのがCORSという仕組みで、ざっくり言うとリソース(ここではAssetBundle)が置いてあるサーバ側でどのドメインからならアクセスを許可するか、を設定でき、許可されていないドメインからのアクセスは全て拒否されます。
つまり今回の場合だとGitHubがlocalhostドメインからのXMLHttpRequestを許可していないから失敗した訳です。
一方githubpagesでは上手くいきました。githubpagesはCORSを*(ワイルドカード)で許可しているらしく、つまりどのドメインが要求してもリソースを渡すようになっているんですね。すばらしい寛容さです。
ちなみにnetlifyもCORSの設定が行えるようなので設定を変更すれば別のドメインからのアクセスを許可することができます。
結果
調査した結果WebGLアプリケーションのAssetBundle置き場として最も適しているのはgithubpagesとなりました。githubpagesはプライベートリポジトリでも利用できるようなので、プロジェクトのリポジトリの/docsフォルダにAssetBundleを置くようにすればプロジェクトの管理とAssetBundleのホスティングを一本化できていいと思います。
ちなみに無料で使えるサービスとしてはOracleCloudFreeTierというのがあり、ある程度の使用量までは無料でOracleCloudを使えるようです。たぶんCORS等の問題も無く月10TBまで転送できるようなので趣味で使う分にはかなり良さそうに思えます。今回の調査対象に含めようとも思ったのですが無料で使用するにもクレジットカードの登録が必要なタイプのサービスだったので断念しました。社会的信用のある方はぜひこちらもお試しください。