はじめに
久しぶりにUnityのWegGLを触る機会に巡りあわせたので、調査内容をまとめてみました。
Unity公式フォーラムでも言われているように、Unity2020.1からはどうやら大きな変更があるみたいです。
今回の基本編では、主にUnity2019.4までと何が変わったのかを確認していきながら、 ビルド時の圧縮についてや、C#,Js(※1)間の連携をみていきたいと思います。
ある程度Unityに触り慣れている人ならすぐにわかるであろうBuild方法などは、 今回は省略しています。
※1:以下この記事では、Js = JavaScript を指します。
開発環境
- Unity2020.1.6f1
- Windows10
- テストしたサーバー環境
- Firebase Hosting
- XAMPP+Apache
※Chromeはローカルでは動きませんでした。ローカルで試したい場合でもサーバーを通す必要があります。
主な変更点
以上の内容を簡略してまとめてみました。詳細はそれぞれのリンクをご覧になってください。
2020/10/12現在、肌感ではありますがまだ公式以外では、Unity2020.1以降の記事は
あまり見受けられないように感じれます。
ほとんどが、Unity2019.4までの内容だと思いますので、バージョンに気を付けて下さい。

なお、Unity2020.1でもモバイルは公式にサポートしていませんが、 こちらのサイトにあるような、上記の警告ダイアログは表示されず、軽いアプリならiPhone、Androidでも正常に 動作しました。
固有のビルドローダ
どうやら汎用的に作られていたのものを最適化して、
読み込みパフォーマンスを上げたみたいです。
ローダーのサイズがUnity2019.3では約155KBだったのが、
Unity2020.1では9KBまで縮小されているとこのことです。
テンプレート変数
以前までの、%VARIABLE%は無くし、 Unity2020.1では下記のようなプリプロセッサ変数が、 .html、.css、.js、.php、で使用出来るようになったみたいです。
Unity側のPlayerSettingsの内容がそのまま使用できるイメージです。
変数名 | 内容 |
---|---|
COMPANY_NAME | 会社名 |
PRODUCT_NAME | 製品名 |
PRODUCT_VERSION | バージョン |
WIDTH | デフォルトのキャンバス幅 |
HEIGHT | デフォルトのキャンバスの高さ |
SPLASH_SCREEN_STYLE | 選択したスプラッシュスタイルに応じて、「DARK」または「LIGHT」に設定されます |
他にもまだたくさんありますので、詳細はマニュアルを見てください。
マクロ
{{{****}}}
のように、中括弧3つでくくることによって、上記のような、
プリプロセッサ変数が使えるようになります。
例
<div id = "unity-build-title"> {{{PRODUCT_NAME}}} </ div>
この場合、Unity側でProductNameを「MyWebGLGame」のように設定していれば、 その文字列が返ってきます。
条件付きディレクティブ
下記のような、条件付きディレクティブを書くことが出来るようになりました。
#if EXPRESSION
// EXPRESSIONがTrueならここを通る。
#else
// 違うのであれば、ここを通る。
#endif
カスタムユーザー変数
以前までは、「UNITY_CUSTOM_」と自作のテンプレート変数はマークする必要がありましたが、
Unity2020.1からはすべて自動的に検出するため不要になったみたいです。
ビルド
Unity2020.1インスタンス化関数が次のように変更されました。
Unity2019.4まで
UnityLoader.instantiate(container, url, override)
Unity2020.1から
createUnityInstance(canvas, config, onProgress).then(onSuccess).catch(onError);
- 引数に<canvas>要素を渡すことが出来るようになり、ページレイアウトを完全に制御できるようになりました。
- ビルド構成オブジェクトを外部JSONに保存せずに、直接引数に渡すようになりました。これによって読み込みパフォーマンスが向上しました。
- Promiseオブジェクトを返すようになりました。
- Jsの知見がある方にとっては常識かもしれないですが、PromiseオブジェクトとはJsの非同期処理を担ってくれるものみたいです。
PlayerSettingsの圧縮方式

ProjectSettings -> Player -> WebGL -> Publishing Settings で設定出来る内容です。 上記画像の赤線の箇所が圧縮の設定です。
Compression Format
圧縮方式 | 公式マニュアルの説明 |
---|---|
gzip | デフォルトのオプションです。GzipファイルはBrotliファイルよりも大きいですが、ビルドが速くHTTPとHTTPSの両方ですべてのブラウザーでネイティブにサポートされています。 |
Brotli | Brotli圧縮は、最高の圧縮率を提供します。Brotliで圧縮されたファイルはgzipよりも小さいですが、圧縮に時間がかかるため、リリースビルドでの反復時間が長くなります。ChromeとFirefoxは、HTTPSを介したBrotli圧縮のみをネイティブにサポートしています。 |
Disabled | 圧縮を無効にします。後処理スクリプトで独自の圧縮を実装する場合は、このオプションを使用します。ホスティングサーバーで静的圧縮を使用する場合にも使用する必要があります。 |
なおこちらのフォーラムではUnity2020では圧縮するとWebアプリの起動に失敗すると言われており、これと同じ現象が起きました。
無圧縮にすることでアプリの起動は出来ましたが、サーバー側の設定で上手くいくのではないかと思います。
Decompression fallback
Js解凍ツールをビルドに埋め込み、ブラウザが圧縮にした場合はコンテンツ を解凍します。 ビルドファイルの読み込みに時間がかかるみたいです。
ファイルサイズが小さいためかもしれないですが、無圧縮との体感的な違い は感じられなかったです。
圧縮方式をどれにしようと、こちらにチェックをいれておくと、アプリ起動に成功しました。
C#、Jsとの相互連携
C#からJsを呼ぶ
Unity2019.4とやり方は変わらないです。
mergeInto(LibraryManager.library, {
Hello: function () {
window.alert("Hello, world!");
},
~省略~
}
マニュアルにあるような、上記Jsを*.jslib
という拡張子で作成します。

それを上記画像のような、Assets/Pluginsフォルダ
に配置します。
using UnityEngine;
using System.Runtime.InteropServices;
public class NewBehaviourScript : MonoBehaviour {
[DllImport("__Internal")]
private static extern void Hello();
void Start() {
Hello();
}
}
次にC#から呼ぶときですが、上記のようにDllImport属性
をつけて、
呼び出します。このあたりはC++のDLL呼び出しと同じ感じだと思います。
JsからC#を呼ぶ
こちらはUnity2019.4と2020.1ではunityInstanceの生成方法が違うため、 参照方法に注意が必要です。
unityInstance.SendMessage('MyGameObject', 'MyFunction');
unityInstance.SendMessage('MyGameObject', 'MyFunction', 5);
unityInstance.SendMessage('MyGameObject', 'MyFunction', 'MyString');
まずJs側ですが、呼び出す関数はどちらのバージョンも上記のように同じです。
- 第一引数:スクリプトをアタッチしているゲームオブジェクトの名前
- 第二引数:スクリプトのPublic関数の名前
- 第三引数:なし or 数字 or 文字列
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
createUnityInstance(canvas, config,
(progress) => {
//プログレスバーの表示の更新
progressBarFull.style.width = 100 * progress + "%";
})
.then((unityInstance) => {
//プログレスバーの表示を消す。
loadingBar.style.display = "none";
//Unityにコールバックを送る。
unityInstance.SendMessage('ReceiveJS', 'SetText', 'CallBack Success.');
})
.catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
なおJsの知見が無い筆者は、createUnityInstance()
の成功した時の
コールバックで受け取れる、unityInstanceから直接呼んで呼ばれるのを確認しました。

このcreateUnityInstance()
はデフォルトのテンプレート(※2)を設定しているのなら、Build後に生成される上記画像のようなindex.html
から確認することが出来ます。
Jsに知見にある方なら、このunityInstanceを任意に参照して、 別のJsライブラリと連携といったことも可能だと思います。
※2:Build後に生成されるHTMLテンプレートのことです。初期はデフォルトに設定されています。
/// <summary>
/// Js側から呼ばれるときのテスト
/// </summary>
public class ReceiveJsSample : MonoBehaviour
{
[SerializeField]
private Text _label;
/// <summary>
/// テキスト設定
/// </summary>
/// <param name="text"></param>
public void SetText(string text)
{
_label.text = text;
}
}
C#側はPublic関数を用意してゲームオブジェクトにアタッチするだけで、簡単です。
まとめ
以前はUnityのWebGLに対してあまり動作しなくて、ネガティブなイメージを持っていましたが、今回久しぶりにUnityのWebGLを触ってみて、思っていたより使いやすくなっているというイメージを抱きました。
さらに最適化も各所に施されていうということで、これからWegGLを触るのであれば Unity2020.1以降が良いのではないかと思います。
次の応用編では、Unityのロゴを消すちょっとしたHTMLの改造と、Unityエンジニア ならよく見かけるであろういつもの"あれ"を表示してみたいと思います。