2D WebView for WebGL brings the 2D functionality of 3D WebView to Unity's HTML5 WebGL player. It functions by loading web content into an <iframe> element, which works well for many 2D scenarios, but due to browser limitations, it has significant limitations compared to the other 3D WebView packages:
- It only supports Native 2D Mode, so the 2D CanvasWebViewPrefab works, but the 3D WebViewPrefab does not. Also, it's not possible to place other Unity objects or UI elements in front of a webview. You can read more about this limitation here.
- It's unable to load websites that block iframes by sending an X-Frame-Options header. For example, many popular sites like Google and Facebook block iframes using X-Frame-Options. You can read more about this limitation and test if a URL is compatible here.
- When the webview's URL has a different domain than the Unity app, most of the IWebView methods become disabled. You can read more about this limitation here. HTML loaded with LoadHtml() also faces this limitation, but an alternative that supports the IWebView methods is to load the HTML from StreamingAssets instead.
- When the Unity app is served over HTTPS (i.e. its URL starts with https://), webviews cannot load insecure HTTP URLs (i.e. https:// must be used instead of http://).
- The following IWebView methods are not supported and are ignored at runtime:
- The following IWebView methods have limitations:
- LoadUrl(url, additionalHeaders) is unable to send additional headers due to browser limitations, so it loads the URL without additional headers.
- CanGoBack() and CanGoForward() both return whether the webview can either go back or forward. In other words, both methods return true if the webview can go either back or foward, and both return false if the webview can't go back or forward.
- LoadProgressChanged only indicates the ProgressChangeType.Started and Finished events, and it is unable to indicate the Failed or Updated events.
Other limitations:
- "Minimal" WebGL template not supported / container element required
- How to use the window.vuplex JavaScript API when the page is from a different domain
- Unity keyboard detection APIs don't work when a webview is focused
2D only limitation
3D WebView normally works by rendering web content to a texture that is shown in Unity. Unfortunately, WebGL doesn't provide a suitable way to render an iframe to a texture, so 2D WebView for WebGL only supports Native 2D Mode. This means that it only supports 2D screen space (it doesn't support 3D world space), and it's not possible to render web content to a texture, render other Unity objects or UI elements in front of a webview, or rotate a webview. In the future, I may develop a separate cloud-based version of 3D WebView that will support 3D in WebGL. If you want me to add you to the waitlist for it, please contact me.
X-Frame-Options limitation
2D WebView for WebGL is unable to load websites that block iframes by sending an X-Frame-Options header. For example, many popular sites like Google and Facebook block iframes using X-Frame-Options. You can determine whether 2D WebView for WebGL can load a given URL by using this URL tester:
Cross-origin domain limitation
For security purposes, browsers prevent a webpage from accessing the content of an iframe if the webpage's URL and the iframe's URL have different domains. For 2D WebView, this means that its IWebView APIs work when the webview's URL matches the domain of the Unity app (for example, when the application loads an HTML file from StreamingAssets or loads a different webpage hosted on your own domain), but most IWebView APIs do not work if the webview's URL is from a different domain (for example, bing.com or any other 3rd party site). When the IWebView APIs are disabled, the user can still click, scroll, and type into the webview directly, but the application cannot interact with the affected IWebView APIs programmatically.
The following IWebView APIs only work when the webview's URL matches the domain of the Unity app:
- CanGoBack()
- CanGoForward()
- CloseRequested
- Click()
- ConsoleMessageLogged
- ExecuteJavaScript()
- FocusedInputFieldChanged
- GoBack()
- GoForward()
- PageLoadScripts
- Scroll()
- SelectAll()
- SendKey()
- SetFocused()
- Title
- TitleChanged
- Url
- UrlChanged
Other notes about this limitation:
LoadHtml() works by loading content as a data URL, which browsers also consider as a different domain. So, HTML loaded with LoadHtml() also faces this limitation, but an alternative that supports the IWebView methods is to load the HTML from StreamingAssets instead.
An application can check check whether the IWebView APIs listed above are enabled at any time by calling WebGLWebView.CanAccessIFrameContent().
"Minimal" WebGL template not supported / container element required
2D WebView for WebGL supports Unity's "Default" and "PWA" WebGL templates, but doesn't support the "Minimal" template. In Unity's "Default" and "PWA" templates, the <canvas> element is nested inside of a parent container element like this:
<div id="unity-container">
<canvas id="unity-canvas"></canvas>
</div>
The elements' styles are set such that the container and canvas have the same position and dimensions (i.e. they have the same rect because the canvas occupies the entirety of the container). 2D WebView for WebGL works by adding <iframe> elements inside the container element so that the iframes are rendered in front of the canvas. Unity's "Minimal" template doesn't include a container element, so 2D WebView for WebGL is unable to support it.
2D WebView can also work with a custom WebGL template as long as the template includes a parent container element with the same dimensions as the <canvas> element, like Unity's "Default" template. 2D WebView automatically detects the container element if its id
is set to "unity-container". If the container element's id
is set to a different value, then the application must call WebGLWebView.SetUnityContainerElementID() to pass the id
value to 2D WebView.
How to use the window.vuplex JavaScript API when the page is from a different domain
Due to the cross-origin domain limitation, 2D WebView for WebGL is unable to automatically inject the window.vuplex
JavaScript API for message passing into a web page if the page's URL is from a different domain than the Unity WebGL app. However, you can add the window.vuplex
JavaScript API to a web page by manually adding the following JavaScript to the page (i.e. via a <script> tag):
class VuplexPolyfill {
constructor() {
this._listeners = {};
window.addEventListener('message', this._handleWindowMessage.bind(this));
}
addEventListener(eventName, listener) {
if (!this._listeners[eventName]) {
this._listeners[eventName] = [];
}
if (this._listeners[eventName].indexOf(listener) === -1) {
this._listeners[eventName].push(listener);
}
}
removeEventListener(eventName, listener) {
if (!this._listeners[eventName]) {
return;
}
const index = this._listeners[eventName].indexOf(listener);
if (index !== -1) {
this._listeners[eventName].splice(index, 1);
}
}
postMessage(message) {
// Don't pass a string to JSON.stringify() because it adds extra quotes.
const messageString = typeof message === 'string' ? message : JSON.stringify(message);
parent.postMessage({
type: 'vuplex.postMessage',
message: messageString
}, '*')
}
_emit(eventName, ...args) {
if (!this._listeners[eventName]) {
return;
}
for (const listener of this._listeners[eventName]) {
try {
listener(...args);
} catch (error) {
console.error(`An error occurred while invoking the '${eventName}' event handler.`, error);
}
}
}
_handleWindowMessage(event) {
if (event.data && event.data.type === 'vuplex.postMessage') {
// Dispatch the new window vuplexmessage event added in v4.11.
const value = event.data.message;
const vuplexMessageEvent = new Event('vuplexmessage');
vuplexMessageEvent.value = value;
vuplexMessageEvent.data = value;
window.dispatchEvent(vuplexMessageEvent);
// Dispatch the older window.vuplex message event.
this._emit('message', { value, data: value });
}
};
}
if (!window.vuplex) {
window.vuplex = new VuplexPolyfill();
}
Unity keyboard detection APIs don't work when a webview is focused
When the user clicks on a webview, their web browser shifts input focus from the Unity game view to the webview's <iframe> element. While the iframe is focused, the Unity application is unable to detect keyboard input (i.e. keyboard APIs like Input.GetKeyDown() don't work). By default, the Unity game view isn't refocused until the user clicks on it, at which point the Unity application is once again able to detect keyboard input. However, the application can optionally use WebGLWebView.SetFocusUnityOnHover() and FocusUnity() to automatically refocus the Unity game view without requiring the user to actually click on it. Please note that these APIs were added in 3D WebView v4.10 and v4.8, respectively.