【Unity】 WebView を狙った位置に表示する

Android

今回はUnityで WebView でのWebページ表示を2DのRectTransformで構成されたUIの中に埋め込んでキレイに表示する方法について説明します。

WebViewはグリーさんから公開いただいているアセット unity-Webviewを使用させていただきます。

こちら記事で環境のセットアップとAndroid端末にWebページを表示させるための簡単なサンプルをまとめておりますので、これをベースに実装をご紹介いたします。




Webview以外のUIの準備

以下のように画面上部に戻る、進むボタンと状態を表示するTextをRectTransformで配置したものを準備しました。

Unity 環境

これらの配置方法など基本的なUnityの使い方は以下のように過去の記事にもまとめておりますので、漁ってみていただければと思います。

この上部のUIより下に画面いっぱいにWebViewを表示するのですが、WebViewはRectTransformで制御することができず、表示はScreenPointの上下左右のマージン座標でしか指定することができません。

WebViewの表示位置の指定方法

前述のUIに対してWebViewをデバイスによらず正しい位置に表示するためには動的に座標を設定する必要があります。今回基準となるオブジェクトは「更新中・・・」と書かれたTextです。

以下の4か所の黄色い矢印の長さを更新中のText Objectの位置を元にScreenサイズで取得できれば位置が求まりそうです。

これら位置を求めるために、まずはUnity Editor上でCanvasを正しく設定しておきます。

Canvasの設定

CanvasはRenderModeをScreen Space – CameraにしてRender CameraにMain Cameraを設定します。

Canvas設定

カメラからScreen座標を求めるのですが、こうしておかないと正しい値が取れません。

表示位置調整スクリプト

続いて表示位置を調整するスクリプトを示します。

using System;
using System.Collections;
using UnityEngine;
#if UNITY_2018_4_OR_NEWER
using UnityEngine.Networking;
#endif
using UnityEngine.UI;

public class WebViewSample : MonoBehaviour
{
    WebViewObject webViewObject;

    public GameObject BaseTargetPanel;

    void Start()
    {
        int[] margins = new int[4];
        Vector3[] corners = new Vector3[4];
        /* Textエリアの4箇所の座標を取得 */
        /* 左下、左上、右上、右下 */
        BaseTargetPanel.GetComponent<RectTransform>().GetWorldCorners(corners);

        /* Textエリアの4箇所の座標をScreen座標に変換 */
        Vector2[] spos = new Vector2[4];
        spos[0] = Camera.main.WorldToScreenPoint(corners[0]); /* 左下 */
        spos[1] = Camera.main.WorldToScreenPoint(corners[1]); /* 左上 */
        spos[2] = Camera.main.WorldToScreenPoint(corners[2]); /* 右上 */
        spos[3] = Camera.main.WorldToScreenPoint(corners[3]); /* 右下 */

        /* 黄色矢印の長さを計算 */
        margins[0] = Math.Abs((int)spos[0].x); /* 左オフセット */
        margins[1] = margins[0] + Math.Abs(Screen.height - (int)spos[0].y + (int)spos[0].x); /* 上オフセット */
        margins[2] = margins[0]; /* 右オフセット */
        margins[3] = margins[0]; /* 下オフセット */

        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
        webViewObject.LoadURL("https://www.google.co.jp");
        /* 表示位置を決定 */
        webViewObject.SetMargins(margins[0], margins[1], margins[2], margins[3]);
        webViewObject.SetVisibility(true);
    }
}

BaseTargetPanelというのはTextのオブジェクトをEditorで設定しておきます。World座標を取得した後、Camera.main.WorldToScreenPointでScreen座標を取得しています。

Screen座標は原点が画面左下になりますので、margineの設定はそれを基準に計算しています。

今回は左、右、下のマージンは等しくしており、spos[0]のみで等幅に合わせています。また、上マージンもspos[0]から計算しています。spos[1]~spos[3]は使用していません。

表示したい状況に応じて基準となるオブジェクトの位置からどの程度離れているかをこのスクリプトを参考に計算すれば、2D UI上の好きな位置に狙ってWebViewを配置することができるかと思います。

その他注意点

座標を取得する時、GetWorldCornersで4点の座標を求めますが、オブジェクトの位置が初期に定まっていない時、正しい座標が取れないことがあります。

具体的には例えば以下のようにContent Size FitterがPreferred Sizeになっていて、RectTransformのHeightがグレーアウトされているような場合です。

Content Size Fitter

Startでこのオブジェクトの座標を取得しに行ったとき、Heightとなる中身がない状態(未初期化?)だと高さ0の座標が取れてしまいます

これを防ぐ方法は色々あるかと思いますが、簡単なのはUnconstrainedに設定して高さを固定してしまう(中身に依存しない)方法です。

こうしておけば、どのタイミングで座標を取得しても正しい座標を取得することができます。

デバイスでの表示位置確認

このスクリプトを画面サイズの異なるデバイスで動作させてみました。どのようなアスペクト比の画面であってもボタンやTextを隠すことなく正しい位置にWebViewが配置されました。

SO-04J
SO-03L

おわりに

オブジェクトのScreen座標を正しく取得さえすれば、好きな位置にWebViewを表示することができます。それは2Dでも3Dでも同様で、デバイス毎に異なるScreen座標を動的に計算、設定することが必要となります。

ちなみに、ノッチのサイズなどもScreen座標で取得することができます。これらも考慮してWebViewを表示させることが大事です。

コメント

  1. […] 【Unity】 WebView を狙った位置に表示するUnityでWebページを表示できるグリー… […]

  2. […] 【Unity】 WebView を狙った位置に表示する今回はUnityで WebView でのWebページ表… 【Unity】 WebView で表示状態とURLを取得するUnityで WebView を使うにあたって、表示中のURLの文字列やページの更新状況、ページの進む戻るといった制御をしたくなるケースが出てくるかと思います。今回はこれら基本的なブラウザ制御手順について説明します。なお、…hirokuma.blog2021.03.09 […]