前言

之前Unity3d的程序在win pc上打开网页一般使用EmbeddedBrowser插件,也算是比较好用的,不过经过查找我发现3D WebView for Windows and macOS (Web Browser)插件也很不错。支持?Vuplex VR/AR 浏览器的相同代码,轻松地在 Windows 和 macOS 上以 3D 形式渲染 Web 内容并与之进行交互。支持Android、iOS、Windows、macOS?和?UWP/Hololens这些平台,不过这里的版本仅支持Windows and macOS平台。其余的平台需要下载其他版本。支持调用键盘和鼠标事件,以编程方式调整大小、缩放、滚动和后退/前进;支持在当前页面的上下文中执行 JavaScript; 支持将消息从JavaScript(网页) 发送到 C# 或者反向发送;支持监听浏览器事件,例如TitleChanged、UrlChanged以及PageLoadFailed;支持查看 PDF;支持在世界坐标系内和UI画布上打开网页。功能很齐全,但是价格也很不美丽。

效果

这是打开网页:

unity 打开手机自带浏览器 unity3d 浏览器_JSON

 VR中应用:

unity 打开手机自带浏览器 unity3d 浏览器_Windows_02

打开网页

这里就使用CanvasWebViewPrefab?快速上手,打开网页它们会自动渲染为 Texture2D 并处理用户互动(单击、滚动、悬停、拖动)。

准备场景

新建一个场景,并新建一个Canvas。
导入插件后,找到Assets\Vuplex\WebView\Core\Prefabs\Resources\CanvasWebViewPrefab.prefab预设:

unity 打开手机自带浏览器 unity3d 浏览器_Windows_03

 将其拖到Canvas下。

编写代码

这里我们在运行就打开Unity官网:

using UnityEngine;
using Vuplex.WebView;

public class test : MonoBehaviour
{
    public CanvasWebViewPrefab canvasWebView;

    async void Start()
    {
        await canvasWebView.WaitUntilInitialized();

        canvasWebView.WebView.LoadUrl("https://unity.cn/");
    }
}

 将脚本组件挂到场景,并将canvasWebView关联起来。

运行起来效果:

unity 打开手机自带浏览器 unity3d 浏览器_Click_04

Unity执行页面JS

这个主要调用ExecuteJavaScript来实现,该函数有两个重载:

void?ExecuteJavaScript(string?javaScript,?Action<string>?callback)
Task<string>?ExecuteJavaScript(string?javaScript)

 为了运行 JavaScript,必须首先加载网页。您可以使用WaitForNextPageLoadToFinish()或LoadProgressChanged事件在页面加载后运行 JavaScript。

如:

await webViewPrefab.WaitUntilInitialized();
 await webViewPrefab.WebView.WaitForNextPageLoadToFinish(); 
var headerText = await webViewPrefab.WebView.ExecuteJavaScript("document.getElementsByTagName('h1')[0].innerText"); 
Debug.Log("H1 text: " + headerText);

 这就是找到标签名 h1并输出它的文本。

Unity与网页消息通信

使用该插件是可以实现 Unity与网页的双向通信,只不过要对接完美,需要两边的开发者协商好通信消息以及格式。

Unity向网页发消息

从 Unity向 网页 发送消息是使用PostMessage()函数来实现。
发送消息的 C# 脚本:

async void Start() {
    var webViewPrefab = GameObject.Find("WebViewPrefab").GetComponent<WebViewPrefab>();
    // Wait for the WebViewPrefab to initialize, because the WebViewPrefab.WebView property
    // is null until the prefab has initialized.
    await webViewPrefab.WaitUntilInitialized();
    // Send a message after the page has loaded.
    await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
    webViewPrefab.WebView.PostMessage("{\"type\": \"greeting\", \"message\": \"Hello from C#!\"}");
}

在网页端,通过对象?message事件监听消息的 JavaScript : 

if (window.vuplex) {
    addMessageListener();
} else {
    window.addEventListener('vuplexready', addMessageListener);
}function addMessageListener() {
    window.vuplex.addEventListener('message', function(event) {
        let json = event.data;
        // > JSON received: { "type": "greeting", "message": "Hello from C#!" }
        console.log('JSON received: ' + json);
    });
}

网页向Unity发消息

3D WebView 有一个内置的window.vuplex.postMessage() JavaScript API,可用于将消息从 网页发送到 Unity。由于它内置在浏览器中,因此您无需在页面中包含任何第三方脚本即可使用它。以下为发消息示例脚本:

// The window.vuplex object gets created when the page starts loading,// so we double-check that it exists before using it here.// You can skip this step if you're sending a message after the page has loaded.
if (window.vuplex) {
    // The window.vuplex object already exists, so go ahead and send the message.
    sendMessageToCSharp();
} else {
    // The window.vuplex object hasn't been initialized yet because the page is still
    // loading, so add an event listener to send the message once it's initialized.
    window.addEventListener('vuplexready', sendMessageToCSharp);
}function sendMessageToCSharp() {
    // This object passed to postMessage() automatically gets serialized as JSON
    // and is emitted via the C# MessageEmitted event. This API mimics the window.postMessage API.
    window.vuplex.postMessage({ type: 'greeting', message: 'Hello from JavaScript!' });
}

在Unity端通过MessageEmitted 事件的监听来接收网页发送过来的消息。
Unity 中接收该消息脚本示例:

async void Start() {
    // This assumes that there's a WebViewPrefab already in the scene.
    var webViewPrefab = GameObject.Find("WebViewPrefab").GetComponent<WebViewPrefab>();
    // Wait for the WebViewPrefab to initialize, because the WebViewPrefab.WebView property
    // is null until the prefab has initialized.
    await webViewPrefab.WaitUntilInitialized();
    webViewPrefab.WebView.MessageEmitted += (sender, eventArgs) => {
        // > JSON received: { "type": "greeting", "message": "Hello from JavaScript!" }
        Debug.Log("JSON received: " + eventArgs.Value);
    };
}

其它

Unity模拟点击网页

通过click函数来实现:

void?Click(Vector2?normalizedPoint,?bool?preventStealingFocus?= false)

示例脚本:

// Click in the exact center of the page.
webViewPrefab.WebView.Click(new Vector2(0.5f, 0.5f));
// Click in the upper right quadrant of the page// and prevent stealing focus from another webview.
webViewPrefab.WebView.Click(new Vector2(0.75f, 0.25f), true);

只不过normalizedPoint是采用标准化点而不是像素坐标,即Vector2? 每个元素的取值范围 0–1。

Unity操作网页文本

选择所有文本,具体取决于页面的焦点元素

webViewPrefab.WebView.SelectAll();

将选定的文本复制到剪贴板:

webViewPrefab.WebView.Copy();

将选定的文本复制到剪贴板并将其删除: 

webViewPrefab.WebView.Cut();