自粛生活が続き、近くのコンビニ行くだけで疲れて「ヤバイ!」と思ったクライアントエンジニアの本多です。
今回はUnityでWebViewを導入し、iOS/Androidで動作をさせる方法を紹介します。
WebViewを利用することで、用意したhtmlや公開されているweb等をUnity上に表示がすることできます。
これにより、クライアントの更新なしに開発者からお知らせを表示したり、ゲームのヘルプなどを表示する機能が実現できます。
導入編
今回使用するプラグイン
https://github.com/gree/unity-webview
こちらを使用しました。
グリー社が提供しており、様々なゲームアプリでも採用されているプラグインです。
今回はUnity2019.3.0f6での実装となります。
新しいプロジェクトを作成し、空のシーンを用意してください。
プラグイン導入手順
プラグインリポジトリ内のdist/unity-webview.unitypackageをダブルクリックなどして全てをImportすることで、unity-webviewの導入は完了です!
unitypackage化されているので、簡単に導入できますね!
今回使用するスクリプト
作成したシーンにGameObjectを作成し、そのGameObjectに以下のWebViewSampleというスクリプトを実装し、アタッチしてください。
using UnityEngine;
public class WebViewSample : MonoBehaviour
{
WebViewObject webViewObject;
void Start()
{
webViewObject = (new GameObject("WebViewObject")).AddComponent<WebViewObject>();
webViewObject.Init(
ld: (msg) => Debug.Log(string.Format("CallOnLoaded[{0}]", msg)),
enableWKWebView: true);
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
webViewObject.bitmapRefreshCycle = 1;
#endif
// お好きなMarginにしてください
webViewObject.SetMargins(100, 100, 100, 100);
webViewObject.SetVisibility(true);
// お好きなURLにしてください
webViewObject.LoadURL("https://www.google.co.jp");
}
void OnGUI()
{
GUI.enabled = webViewObject.CanGoBack();
if (GUI.Button(new Rect(10, 10, 80, 80), "<"))
{
// ブラウザ:前のページへ
webViewObject.GoBack();
}
GUI.enabled = true;
GUI.enabled = webViewObject.CanGoForward();
if (GUI.Button(new Rect(100, 10, 80, 80), ">"))
{
// ブラウザ:次のページへ
webViewObject.GoForward();
}
GUI.enabled = true;
}
}
ここまで実装していただくと、サンプルシーン起動時に下の添付画像のような動作になります!
ビルド方法
IOS/Android共に通常通りビルドを行うことで問題ありません!
WebViewはサンプルシーンや導入、ビルド共に結構単純なので良いですね!
WebView実装/導入時のトラブルシューティング
Unity EditorでWebViewを読み込もうとするとUnityがクラッシュしてしまう!
公式のReadmeにも記述されていますがMetal Editor SupportをOffにしなければなりません。
上記をOffにしないと、Unityがクラッシュしてしまいます。
方法は
- Unity EditorでツールからEditor -> ProjectSettings -> Playerを選択
- 一番左のUnity EditorタブのOther SettingsからMetal Editor Supportのチェックボックスを外してください!
上記二つを行っていただくことで、クラッシュしなくなります。
以下参考画像
Iosビルド(XCode)でコンパイルエラーが発生した!
XCodeでビルドをした際にExpected expressionといったエラーが起きてしまうことがあります。
(XCode10.1でこのエラーは確認できました。)
対処法としては2つあり、
- XCode11系にあげる。
- 該当のエラーを修正する。
の2つがあります。
何か理由がない限りはXCode11系にあげるのが良いと思います。
下記に「該当のエラーを修正する」方法を記述します。
該当のエラーを修正する方法
XCodeプロジェクト内にあるWebView.mmファイルの512行目に記述されている
- (BOOL)setURLPattern:(const char *)allowPattern and:(const char *)denyPattern and:(const char *)hookPattern
を
- (BOOL)setURLPattern:(const char *)allowPattern denyPattern:(const char *)denyPattern and:(const char *)hookPattern
に変更
XCodeプロジェクト内にあるWebView.mmファイルの746行目に記述されている
return [webViewPlugin setURLPattern:allowPattern and:denyPattern and:hookPattern];
を
return [webViewPlugin setURLPattern:allowPattern denyPattern:denyPattern denyPattern:hookPattern];
に変更
といったように
andと記述されている文字列を好きな文字列に変えていただければコンパイルが通ります。
おそらく、andという変数がXCode10系では標準用意されている変数なのでコンパイルが通らないのではという推測です。
実践編
Marginを指定オブジェクトの大きさに合わせたい
サンプルコード内に記述されていた
webViewObject.SetMargins(100, 100, 100, 100);
の固定数字をuGUI上のオブジェクトの大きさから計算する方法を紹介します。
方法としては、
- Marginを合わせたいObjectからCanvas、Camera、RectTransformを取得
- RectTransformからWorldCorners(ワールド空間上の頂点)を取得
- 取得したワールド空間上の頂点からScreenCornersを取得(スクリーン空間上の頂点)
- 取得したスクリーン空間上の頂点からマージンを計算する
といったフローです。
実際のソースコード(メソッドのみ)
// target:Marginを合わせたいObject
int[] CalcMargins(GameObject target)
{
int[] margins = { 0, 0, 0, 0 };
Camera camera = null;
var canvas = target.GetComponentInParent<Canvas>();
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay) camera = canvas.worldCamera;
var rectTransform = (RectTransform)target.transform;
Vector3[] targetWorldCorners = new Vector3[4];
rectTransform.GetWorldCorners(targetWorldCorners);
Vector2[] targetScreenCorners = new Vector2[4];
targetScreenCorners = WorldCornersToScreenCorners(camera, targetWorldCorners);
// ScreenCornersは0:左下、1:左上、2:右上、3:右下
// Screen空間では左下が(0, 0)右上が(Screen.width, Screen.height)なので左下、右上を基準で計算
// marginsは0:左、1:上、2:右、3:下
margins[0] = Math.Abs((int)targetScreenCorners[0].x);
margins[1] = Math.Abs(Screen.height - (int)targetScreenCorners[2].y);
margins[2] = Math.Abs(Screen.width - (int)targetScreenCorners[2].x);
margins[3] = Math.Abs((int)targetScreenCorners[0].y);
return margins;
}
上記を実装し、
public class WebViewSample
{
[SerializeField] GameObject targetObject;
WebViewObject webViewObject;
void Start()
{
// ~~~一部抜粋~~~
margins = CalcMargins(targetObject);
webViewObject.SetMargins(margins[0], margins[1], margins[2], margins[3]);
// ~~~一部抜粋~~~
}
}
のようなやり方で動的にオブジェクトの大きさからMarginを計算することができます。
おわりに
今回はWebViewの導入/実装、トラブルシューティング、uGUIのオブジェクトサイズに合わせる実践的な方法を説明しました!
WebViewの導入自体はそれほど難しくありませんが、実機でのみ起きてしまう問題やゲームの内部処理と連携させる部分が難しいポイントです。
しかし、様々な仕組みに応用出来る可能性があるところが魅力的ですね!
皆さんも是非WebView導入にチャレンジしてみてください!