15
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Unity #3Advent Calendar 2019

Day 20

AssetBundle置き場を探す

Last updated at Posted at 2019-12-19

どこに置く?

先日AssetBundleを使う機会がありました。
UnityRoomで利用したかったので外部でホスティングする必要があるのですが、どこに置いたらいいんでしょうか?
GCSとかS3とかでいいんじゃ、と思われるかもしれませんがこれらのストレージサービスは金がかかります。大した金額にはならないと思いますが、なるべく無料の範囲で抑えたいのが人情でしょう。今回はAssetBundle置き場として、無料のストレージサービスやホスティングサービスをいくつか試してみました。

調査対象

Dropbox, GoogleDrive, netlify, github, githubpages
の5つです。
なおこの記事はこれらのサービスでAssetBundleのホスティングが可能であることを保証するものではありません。商用非商用を問わず各サービスの利用規約を読んで自己責任でお願いします。ダメだよとかいけるよとか知っている人はコメントください。

調査方法

cds.png

DLManager.cs
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
ネット環境
speedResult.png

調査1:ローカル実行

僕の当初の目的はWebGLアプリケーションなのですがWebGLとローカル(スタンドアロンとかエディタ上とか)では結果が変わってくるかもしれないのでまずはエディタ上で見ていきたいと思います。

GoogleDrive

ストレージサービスと言えばまずはこれでしょう。ちなみに共有用のリンクを少し書き換える必要があります。こちらの記事を参考にさせて頂きました。
googledrive_local.png

Dropbox

こちらもまたストレージサービスの代名詞ですね。
dropbox_local.png
こちらも共有リンクを少し書き換える必要があります。末尾のdl=0をdl=1にするだけです。

netlify

ウェブ屋さんなら誰でも知ってる話題のホスティングサービスですね。僕はウェブ屋さんじゃないのでつい最近まで知りませんでした。
netlify_local.png

github

あのgithubです。期待できそうですね。
github_local.png

githubpages

あのgithubのホスティングサービスです。期待できそうですね。
githubio_local.png

結果

サービス名 結果[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

googledrive_cors.png
あれ?

Dropbox

dropbox_cors.png
ん?

netlify

netlify_cors.png
おかしい...

github

github_cors.png
なんで?

githubpages

githubio_webgl.png
ようやく結果が出ました。

結果

サービス名 結果[sec]
GoogleDrive 失敗
Dropbox 失敗
netlify 失敗
github 失敗
githubpages 19.72
githubpagesを除く全てのサービスで失敗してしまいました。一体どうしたことでしょう。

その名もCORS

F12を押してエラーメッセージを見てみましょう。
cors.png
ウェブを触ったことある人なら見たことあるのではないでしょうか。僕はウェブを触ったことが無いので初めて見ました。
これは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まで転送できるようなので趣味で使う分にはかなり良さそうに思えます。今回の調査対象に含めようとも思ったのですが無料で使用するにもクレジットカードの登録が必要なタイプのサービスだったので断念しました。社会的信用のある方はぜひこちらもお試しください。

15
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?