HTML5 Conference 2016特集・第5弾は、「Unity WebGL入門」です。WebGL正式対応により、ゲームをはじめとしたブラウザコンテンツ制作ツールとして広く使われるようになったUnityの概要及びWebGLへの書き出しについて解説します。
WebGLにも対応したUnityのいま
Unityは統合的なインタラクティブコンテンツ制作ツールです。
無料で使えるPersonalから文字通りプロフェッショナルのためのProまで3つのサブスクリプション・プランを用意していますが、根幹となるUnityエディタの機能はどのプランも同一のものとなっており、対応プラットフォームにも違いがありません。つまり、Personalでも強力な3D表現が実現できてしまうのです。
そして2015年末にリリースされたバージョン5.3より、Unityは正式にWebGLに対応し、ゲームを始めとしたブラウザ上でのリッチコンテンツの作成環境として広く使われるようになりました。その後も着実に進化を続け、次期バージョンである5.5ではWebAssembly対応による飛躍的なパフォーマンスの向上が見込まれています。本稿ではUnityのWebGLの概要に始まり、実際にコンテンツ開発を始めるにあたって注意すべき点などを紹介します。
パフォーマンス
Unityをコンテンツ開発の選択肢に挙げるにあたりユーザー最も気にするのは「どの程度のものが作れるのか」という話ではないでしょうか。結論から言うと、iOSやAndoriodなどのUnity製のモバイルネイティブアプリと概ね近しいクオリティが得られます。
特にグラフィックの表現力はWebGL2.0をブラウザでの正式対応に先んじてサポートしており、Unity内で一般的な3Dオブジェクトに使われるStandard Shaderでの描画能力はモバイルよりもデスクトップに近く、ソフトシャドウを使うことも可能です。
反面、マルチスレッド非対応やヒープ領域の制限、ファイルシステムを持たないなどの理由によりCPUとメモリはボトルネックになりやすく、パフォーマンスを引き出すためにはそれらを考慮した実装を考える必要があります。
また、スマートフォンなどのモバイル版ブラウザは現在のところ未対応となっており対応時期も未定です。シンプルなプロジェクトであれば大きな支障なく動作することもありますが、「まあ動くこともある」程度に捉えていただくのが無難です。
Unity WebGLを支える技術
WebGLで実行するためにはコードがJavascriptで書かれている必要がありますが、UnityはEmscripten コンパイラーツールチェーンを使用し、CおよびC++で記述されているUnityのランタイムコードをビルド時にasm.js JavaScript にクロスコンパイルしています。
ams.jsとは高速化を目的としたJavaScript言語仕様のサブセットであり、事前コンパイル(AOT)された形で実行されます。過去にはFireFoxのみに対応していたこの技術も今や多くの主要ブラウザが対応しており、ブラウザ間でのパフォーマンスの差は徐々に埋まりつつあります。また非対応のIEではパフォーマンスに大きな難を抱えています。
では、開発者が記述することになるユーザーコードはどうでしょうか。Unityは.Net互換のMono環境で実行されるので、ユーザーはC#あるいはUnity独自の言語であるUnity Scriptでの開発がメインとなります。
Unityはビルドする際、通常は書き出されたCIL(中間言語)をmonoのランタイムにより各プラットフォームのネイティブコードに変換するわけですが、WebGLをターゲットとした場合はUnityの独自技術であるIL2CPPにより一旦C++に変換し、その後はUnityのランタイムコードと概ね同じ手順でJavascriptに変換されます。
IL2CPPはUnityが多くのプラットフォームに展開、そして最適化するための重要な技術です。
Unityでの設定のポイント
WEBコンテンツである以上、ビルドサイズを少しでも削減することは大きな課題と言えるでしょう。
エンジンコード、及びユーザーの記述したコードについてはリリースビルドとして書き出すことで縮小化、gzip圧縮され、ダウンロード後にブラウザ上で解凍、及びパージングして実行されます。さらにStrip Engine Codeオプションにより使用しないエンジンの機能をあらかじめ削除しておくことができます。
シーンファイル及びシーン内で使用されるアセットはアーカイブデータとして通常1ファイルにまとめられます。
サーバからは上記同様gzip圧縮したものをブラウザ上で展開し、得られたファイルはさらにLZ4形式で圧縮されています。ブラウザのタブを閉じるまでメモリ内にストックされ、使用すべきアセットがロードするときだけ解凍される仕様です。
しかし2種類の圧縮がかかっているとはいえ大量のテクスチャやサウンドを含むデータをコンテンツ開始時に一度にロードさせ、メモリ内に保持し続けることは得策ではありません。ダウンロード時間とメモリ使用量の削減を両立させるためにはhtmlから直接参照されるアセットを最小限に留め、それ以外をAsset Bundleで提供することが望ましいと言えます。
Asset Bundleは簡単に言うとアセットをシリアライズしたアーカイブファイルです。実行時にサーバからダウンロードして利用するため読み込みのタイミングを管理し、必要なくなったタイミングで破棄し、メモリを解放することができます。使用の際は通常アセット同様にチャンクベースの圧縮形式LZ4が多くのケースで有用です。
Unityの提供するサービスとの連携
前述した通り、WebGLへのビルドは複雑な手順で行われており、他のプラットフォームに比べ時間を要します。CIサーバを用意して自動化するという解決法もありますが、もっと手軽な方法としてUnityはクラウド上でビルドを行うサービスを提供しており、サービス内容に差はあるものの全てのプランで無料提供されています。
GitやSubversionなど広く使われるソースコントロールであればリポジトリを更新するだけで自動的に行われ、書き出されたURLを伝えればどこからでも確認できるようになります。またAssetBandleのビルドもサポートしており、開発効率を上げるためには欠かせないサービスとなっています。
その他にもユーザーの環境や動向を分析するUnityアナリティクスや、Unityエディタに統合された簡易的なソースコンントロールであるUnityコラボレイトなど、Unityの提供するサービスは広がり続けています。
まとめ
冒頭でも述べましたが、Unityは統合的なインタラクティブコンテンツ制作ツールであり、WebGLを構築するためのJSライブラリ等とはアプローチが大きく異なります。
特に3Dビューに慣れていない方は最初は戸惑われるかもしれません。しかしユーザー数やコミュニティに後押しされる形で多くの情報をWebで手軽に入手できるほか、チュートリアルや入門書籍なども充実しています。一度是非お試しください。
当日の資料と動画は下記で公開されていますので、こちらも参照してください。