追記(2014/05/05)
現在、本エントリで利用している Awesomium v1.6.2 はダウンロード出来ないため、v1.7.1 を利用したエントリを書きました:
ただし Mac では利用できません。
はじめに
Unity 上で Web を表示できるプラグインについて調べてみました。
デモ
出来るようになることのデモ動画です:
参考
Plugin の種類
Unity 上で Web を表示する方法は沢山あるようです。
- unity-webview-integration
- GitHub - keijiro/unity-webview-integration: Unity iOS および Android における web view 組み込み例
- PF: Android / iOS
- unity-webview の元になったプラグイン。
- unity-webview
- HtmlTexturePlugin
- UnityWebCore
- Unity3d plugin for embedding webpages on WINDOWS is ready! - Unity Forum
- PF: Windows で Standalone のみ
- uWebKit
- http://uwebkit.com/uwebkit/
- PF: Windows / Mac / iOS
- 有償です
- UnityBerkeliumPlugin
- GitHub - jdierckx/UnityBerkeliumPlugin: A wrapper plugin around the Berkelium library to render and interact with web pages inside Unity3D
- PF: Windows
- Chromium をバックエンドに使ったヘッドレスブラウザ Berkelium を Unity でラップしたプラグイン
- Awesomium integration
- PF: Windows / Mac
- Awesomium も同様のヘッドレスブラウザですが商用などは有償です(Ultralight - Next-Generation HTML Renderer for Desktop Apps and Games)
この他にも PhantomJS などのヘッドレスブラウザと通信して…、みたいなことをやっている人も居ました。
Unity だと少々面倒くさい UI の構築の代替 & モバイル向け広告などの用途であれば unity-webview が良いように思われます(何もせずとも正常に動作してお手軽です)。私はテクスチャとして利用したかったので、Mac なら HtmlTexturePlugin、Win なら Berkelium が素性が良さそうです。また、Berkelium は Mac でも行けるとの情報もありました。Win/Mac 両方いける Awesomium は商用は有償ですが、個人開発用途では無料のようなので最も良さそうに思えます。
そこで、HtmlTexturePlugin、Berkelium、Awesomium について調べてみました。結果としては Awesomium が Win / Mac 共に動作したのでこれをメインで解説します。HtmlTexturePlugin と Berkelium は正常な動作まで持っていけませんでしたが、失敗談を後述します。
Awesomium(Mac)
手順は Awesomium v1.6.2 のようで、現行の v1.7.1 に対するチュートリアルは見つかりませんでした。そこでフォーラムで検索してみました。
- Ultralight - Next-Generation HTML Renderer for Desktop Apps and Games
- Ultralight - Next-Generation HTML Renderer for Desktop Apps and Games
殺伐としている…、もう少し待ってね、という内容から進捗がないようです。v1.7.1 で v1.6.2 のチュートリアルに従ってやってみましたが、「EntryPointNotFoundException」で落ちてしまいました。自前でバインディングするのはコストが高いので、なるべく楽にできそうな方法を探します。
古いバージョンを探す
ここに書いてある v1.6.5 のキャッシュを試してみましたが、Unity が落ちて駄目でした。
v1.6.2 を探す
やはり、v1.6.2 でなければ駄目なようです。そこでものは試しと、上記リンクの v1.6.5 の部分を v1.6.2 に変えてみました。
あった!やってみるものですね。
そして上手く行ったのでこの手順を記しておきます。
まず、「build/bin/release/Awesomium.framework」を 「/Applications/Unity.app/Contents/Frameworks」に移動します。これで Unity 上から Framework を参照できるようになります。
次に以下の github より「UnityAwe」を落としてきます。
適当な Unity の新しいプロジェクトを作成し、「bin/mac/AwesomiumMono.dll」「WebCoreHelper.cs」「WebTexture.cs」の 3 点を Unity の「Project」へ放り込みます。そして、「WebTexture.cs」を Plane に追加して、テクスチャサイズと URL を指定して実行すると、以下のように表示されます。
ゲーム画面ではスクロールやリンククリックともに可能です!素晴らしい。
しかしながら、ゲームの実行を終了すると Unity が落ちます。これを回避するためには以下の2箇所を修正して下さい。
WebTexture.cs: 127 行目
private void OnDisable() { // Free the pinned array handle. PixelsHandle.Free(); webViewList.Remove(webView); webView = null; if (WebCore.IsRunning) webView.Close(); }
webView が null になった後に Close() され得るので、以下のように順番を入れ替えます。
private void OnDisable() { // Free the pinned array handle. PixelsHandle.Free(); if (WebCore.IsRunning) webView.Close(); webViewList.Remove(webView); webView = null; }
WebTexture.cs: 238 行目
private void OnApplicationQuit() { // We shutdown the WebCore only once if (WebCore.IsRunning) { Destroy(GameObject.Find("WebCoreHelperInstance")); WebCore.Shutdown(); } }
この「Shutdown」で落ちるので、内部の処理を肩代わりしようかと思ったのですが private メンバでアクセス出来ないので、メモリリークに目を瞑りつつ泣く泣くコメントアウトします。
private void OnApplicationQuit() { // We shutdown the WebCore only once if (WebCore.IsRunning) { Destroy(GameObject.Find("WebCoreHelperInstance")); // WebCore.Shutdown(); } }
これで落ちずに動くようになります。
Awesomium(Windows)
Windows も同様の手順で行えば OK です。
- Windows 用の SDK の v1.6.2 をダウンロードしてインストール
- デスクトップにできた「awesomium_v1.6.2_sdk_win\build\bin\release」の中身を「C:\Program Files (x86)\Unity\Editor」へコピー
- github より「UnityAwe」をダウンロード
- 「bin\win\AwesomiumMono.dll」「WebCoreHelper.cs」「WebTexture.cs」を Project ビューへドラッグ&ドロップ
- 適当なプレーンに「WebTexture.cs」をアタッチして Width / Height / Initial URL を指定
- 実行
Windows は Mac と違ってエラーが出て落ちるということはありませんでした。ただ終了時に「Non matching Profiler.EndSample」というプロファイラ関連のエラーが吐かれてしまいます。調べた所、Unity のバグではないか、とのことでした。
特に困ることは無いので放っておきます。
複数テクスチャのレンダリング
WebCore は共有しているので 2 枚、3 枚の WebView のレンダリングも良い感じの速度で動きます。もちろんプレーン以外の形状にもテクスチャとして貼り付けられます。ただその場合は操作は破綻しますのでご注意を。
ビルド
公開する際はそのまま Build & Run しただけでは動きません。
Mac
- ビルドしたアプリケーションを右クリックして「パッケージの内容を表示」をクリック
- 「Contents/Framework」内に先ほど同様に「Awesomium.framework」を入れる
Awesomium の機能を調べてみる
せっかく動くようになったので機能を調べてみます。基本的な機能(ナビゲーション等)は WebTexture が既にメンバとして持っています。より踏み込んだ機能を使いたい場合は、以下の API リファレンスを参考に直接 WebView の public メンバを利用します。
欲しいものはひと通り揃っている感じしますね。試しに ExecuteJavascriptWithResult を以下のように Update 内に仕込んでみます。
if ( Input.GetKeyDown(KeyCode.A) ) { JSValue result = webView.ExecuteJavascriptWithResult("document.title"); Debug.Log( result.ToString() ); }
これでページタイトルがデバッグビューに表示されます(※ タイトルは Title プロパティからも調べられます)。面白いですね。
(失敗編 1)HtmlTexturePlugin
結論から述べると、一瞬しか表示されない問題に悩まされているので、現状使えていないです…。が、そこまでの手順をメモしておきます。
- 以下からダウンロード
- Assets/Plugins 下に htmlTexture.bundle を移動
- 後述のスクリプトを Plane にアタッチ
- 反転してしまうので x スケール値を負の値に変更
- File > Build & Run から実行
スクリプト
using UnityEngine; using System.Collections; using System.Text; using System.Runtime.InteropServices; public class HtmlTexture : MonoBehaviour { [DllImport ("htmlTexture")] private static extern void htmlTexture_start(int textID, int width, int height, string url); [DllImport ("htmlTexture")] private static extern void htmlTexture_stop(); [DllImport ("htmlTexture")] private static extern void htmlTexture_update(int texID); [DllImport ("htmlTexture")] private static extern void htmlTexture_setURL(int texID, string url); [DllImport ("htmlTexture")] private static extern void htmlTexture_getURL(int texID, StringBuilder url, int stringCapacity); [DllImport ("htmlTexture")] private static extern void htmlTexture_goBack(int texID); [DllImport ("htmlTexture")] private static extern void htmlTexture_goForward(int texID); [DllImport ("htmlTexture")] private static extern void htmlTexture_sendJavascript(int texID, string js); [DllImport ("htmlTexture")] private static extern void htmlTexture_sendJavascript(int texID, string js, StringBuilder result, int stringCapacity); [DllImport ("htmlTexture")] private static extern void htmlTexture_sendKeypress(int texID, string s); [DllImport ("htmlTexture")] private static extern void htmlTexture_mousemoved(int texID, int _x, int _y); [DllImport ("htmlTexture")] private static extern void htmlTexture_mousedown(int texID, int _x, int _y); [DllImport ("htmlTexture")] private static extern void htmlTexture_mouseup(int texID, int _x, int _y); [DllImport ("htmlTexture")] private static extern void htmlTexture_leftclick(int texID, int _x, int _y); public int Width = 1024; public int Height = 512; private Texture2D texture_; void Start() { texture_ = new Texture2D(Width, Height, TextureFormat.ARGB32, false); texture_.Apply(); htmlTexture_start(texture_.GetInstanceID(), Width, Height, "http://google.com"); transform.renderer.sharedMaterial.mainTexture = texture_; } void Update() { htmlTexture_update(texture_.GetInstanceID()); texture_.Apply(); if (Input.GetKeyDown (KeyCode.R)) { htmlTexture_setURL(texture_.GetInstanceID(), "http://google.com"); } } void OnApplicationQuit() { htmlTexture_stop(); } }
何故一瞬しか表示されないのかは不明です…。操作については説明にあるようにここから RayCast を使ってやれば良いようです(正常に表示されればでうが…)。JS のインジェクションも出来て素性がよさそうなだけに残念です。動いた方がいらっしゃいましたら方法を教えて下さい。
(失敗編 2) Berkelium
スレ主の reissgrant さんが作成した Windows 版が大本で、stubborngorilla さんが Mac 版を作成されたようです。が、結論からいうと、どちらも動きませんでした。更新が 3 年前で止まっていることもあり、現環境ではどこか上手く動いていないようです。Windows で試してみた感じは Berkelium.exe 自体がうまく動作していないので(Chromium のバージョンも相当古いです)、新しい Berkelium をビルドしなおせばうまくいくかもしれません。
おわりに
3D と Web の世界の融合は色々な可能性があってとても面白そうです。私は Oculus Rift の世界に Web を持ち込みたいと思っていますので、これを利用して何か作ってみようと思います。