This asset allows you to embed a full copy of Chromium, the open-source core of Google Chrome, inside your game!
Documentation for v1.1.0.
Copyright © 2015-2017 Zen Fulcrum LLC
- If you are using OS X be sure to read these notes.
- Import ZFBrowser into your project.
ZFBrowser/Prefabs/BrowserQuadand drop it into your scene.
- On this new object, set the URL to a site of your choice, such as
- Fiddle with your camera so the quad fills most of the view.
- Hit play and interact with the web site.
- Start with the scene above.
- Create a folder called
BrowserAssetsright next to (not inside!) your
- Create a file called
BrowserAssetsand put this in it:
- Set the URL for the BrowserQuad to
- Hit play.
Congratulations! You now have a browser in your game!
This library is made possible by a number of third-party open source software projects!
Include a copy of ThirdPartyNotices.txt with your distributed product.
This plugin is available for the given platforms and architectures:
- Windows Standalone, 32- and 64-bit (Windows Standalone does not include WSA/UWP)
- OS X Standalone, 64-bit
Browsers can be previewed when running inside the Unity Editor on the following platforms:
- Unity Editor, Windows Standalone, 32- and 64-bit
- Unity Editor, OS X Standalone, 64-bit
At present, you must use the same OS you are targeting to preview in the Unity Editor. For example, you must be running the 64-bit Windows Unity Editor to preview browsers when targeting Windows Standalone x64.
A 64-bit Linux port is partially completed but too unstable for distribution at this time. If you're excited to see this reach completion, send me an email.
This Asset does not includes licenses for proprietary or patent-encumbered codecs such as h.264 and mp3. Consider re-encoding your content with an open codec supported by Chromium or use consider using Adobe Flash to play your content.
- By default, your new Unity project will target universal builds, you'll need to change it to x64 before you can build and run your application.
- The Asset Store strips the executable bit off our child process. After importing the Asset, run a browser in the editor's playmode at least once before exporting a build. This will ensure the permission gets added back so the system can run.
- When running under the Unity Editor in OS X (or Linux), an extra layer of indirection must be used to avoid library conflicts. This reduces performance in the editor. Run a standalone build to see actual performance.
- At present, OS X builds must be made from OS X.
You can send and receive messages from the currently loaded browser page.
Browsers have a
Browser MonoBehaviour. You can call functions in the page by invoking
using ZenFulcrum.EmbeddedBrowser; ... var browser = GetComponent<Browser>();//assuming we are a MonoBehaviour attached to the same GameObject as the Browser //calls window.setPlayerStats("myPlayerName", 2, 4200, false) in the browser browser.CallFunction("setPlayerStats", "myPlayerName", 2, 4200, false);
Functions are resolved in the global scope of the top frame of the browser and executed with the given arguments. You can pass basic types (strings, integers, bools, etc.) without any extra effort.
You can also use
browser.EvalJS("if (someCondition()) someVar = 42;");
To query the page for data, you can look at the return value.
CallFunction don't execute immediately, they are asynchronous, therefore they return promises:
browser.EvalJS("document.title").Then(ret => Debug.Log("Document title: " + ret)); browser.CallFunction("doSomeFoo", 1, 2, 3).Then(ret => Debug.Log("Result: " + ret));
If you are in a Unity corountine, you can wait for the promises to finish before continuing:
var promise = browser.EvalJS("document.title"); yield return promise.ToWaitFor(); Debug.Log("Document title: " + promise.Value);
This can be much easier to deal with in cases where you are chaining a lot of tasks.
See the promise section for more details on the promise library.
To receive events pushed from the page, you can expose a function callback. Do this with
browser.RegisterFunction("confirmClicked", args => Debug.Log("Button clicked: " + args + " val: " + (int)args));
Then you can call it from your page:
<!-- When this is clicked, Unity will log "Button clicked: button3 val: 13" --> <button onclick="confirmClicked('button3', 13)">Confirm Things</button>
- The functions that return data from a page return a
JSONNode. This class which implicitly converts to basic types like strings and integers. Take a look in JSONNode.cs for more information.
- If you'd like to pass something more complex than a basic type, build a
JSONNodeallows you to build and access JSON data using a fairly fluent language-native interface.
- If you'd like to pass something yet still more complex, or have data automatically read from your objects' fields:
- If the Browser isn't ready for commands or the page isn't loaded yet, it will queue your commands and execute them then the page is loaded.
- Note that functions you expose won't be available at the time of the HTML load event. If you need to know when the page loads, use browser.WhenLoaded (Unity side).
- Check out the included demo and examples for some example code and use cases.
ZFBrowser uses this promise library made by Real Serious Games with some small changes.
This copy has been modified a bit from the version you can get from GitHub, namely:
- The library namespace has been changed from
ZenFulcrum.EmbeddedBrowsernamespace for simplicity and to avoid potential conflicts.
Debug.LogErroris registered by default.
- You can use Promises with coroutines:
yield return somePromise.ForCoroutine();waits for the promise to be rejected or resolved.
- You can query a Promise for its resolved value (or rejection) with
The promise library is covered by the MIT license, as noted in ThirdPartyNoticies.txt.
You can embed web resources (HTML, JS, CSS, images, etc.) with your game and access them without the need for an external web server.
Place these resources in a folder named
BrowserAssets next to your
Assets folder, then access them with
localGame://index.html instead of the usual
- localGame:// is treated like a unique domain and is subject to same-domain policies like other websites.
- If you want to customize or change how these resources are fetched, read the documentation in WebResources.cs.
- In the editor, you can simply refresh a page to see updated changes for changed files.
- File names are case-sensitive! Test your standalone build. Under the Editor some platforms may incorrectly load wRonGcapS successfully.
- When you build, all browser assets are packaged up as a single file and included with the build.
- localGame:// is not the actual URL the browser uses, so don't hardcode it in your HTML. (The real URL is currently
https://game.local/, but may change.)
- Avoid putting untrusted code in BrowserAssets
- You may need to URL-encode your path if it contains non-alphanumeric characters. How to encode
All mouse/keyboard input events are collected in Unity and forwarded to the underlying browser. How this input is sent can be customized.
- Mouse clicks and keyboard events are fed to the Browser via the
IBrowserUIinterface. Additionally, the
IBrowserUIinforms us about mouse cursor changes from the page.
- This package comes with a few useful versions of
IBrowserUIout of the box:
ClickMeshBrowserUI(used by default) - Lets you click and interact with browsers with a free mouse hovering over the scene.
- Requires a mesh collider.
- It projects the mouse's position into the scene with the main camera and a physics raycast.
- UVs on the mesh collider are used to look up the "in-browser" mouse position.
- If the mouse if over the browser it is considered focused and will receive keyboard input.
- Automatically updates the mouse cursor to reflect the currently hovered area.
- Used by default, so long as the browser has a MeshCollider.
FPSBrowserUI- Lets a first-person controlled character interact with items in a scene by walking up and pointing.
- Mouse position is inferred from the direction the camera is pointing.
- Creates a single
FPSCursorRendererin the scene to render the central cursor and crosshair for you.
- Attach to a browser to use it. See the demo for a working example. A prefab is also included.
GUIBrowserUI- For use with full-screen browsers and browsers alongside non-browser UI elements.
- Operates inside a Unity UI Canvas. Renders to a RawImage and intercepts input like other UI elements.
- Drop the BrowserGUI prefab into a canvas element to use.
- You can always create your own input manager by extending one of these or by implementing
browser.UIHandlerto your custom implementation before the first call to browser.Update(). You can also set it to null, which will disable all input.
- Mouse scroll speed and double-click handling options can be adjusted by altering myBrowserUI.InputSettings.
beforeUnloaddialogs and context menus by editing ZFBrowser/Resources/Browser/Dialogs.html
- Customize error pages by editing ZFBrowser/Resources/Browser/Errors.html
- Hook these events by listening to
- Hook these events by listening to
- Mouse cursors are:
- Stored in ZFBrowser/Resources/Browser/Cursors.png. (These are more-or-less the base Chromium icons.)
- Loaded and managed by the
- To change how a current cursor looks without altering the size, just edit Cursors.png.
- If you wish to change the cursor sizes or which cursor types map to which Cursors.png item, take a look at IconGenerator.cs. (This script isn't intended for general use, so be prepared to get your hands dirty.)
Often during development, you will find your pages need debugging.
Tip: You don't always have to restart the game to test a change, in some cases you can simply refresh the page. (Unity inspector -> browser instance -> Refresh or Page inspector -> ctrl+r).
Here's a few way to go about it:
You can access the Webkit/Chromium inspector, which opens in a new window beside the running game.
- Under the Editor in play mode: Select the Browser, then click "Show Dev Tools"
- You can also use browser.ShowDevTools() to open an inspector window.
- This inspector can be a bit unstable at times. If you have issues, try a different debugging method or push Chromium out of process
You can access the page inspector from another browser.
- To debug when running in the Editor, visit http://localhost:9848/
- To debug when running a debug build, visit http://localhost:9849/
- Release builds cannot be debugged using this method.
- Use a same-version-a-the-plugin Chromium-based browser to load the above URLs.
Chromium/CEF don't play nice with Visual Studio Tools for Unity. If you want to use C# debugging with this tool, push Chromium out of process.
Under the Windows Unity Editor we host the root Chromium process within the Unity Editor. This gives us better performance, but causes some issues such as inspector and debugger stability/usability.
If you are having issues, you can push Chromium out of the Editor process. It's a bit slower, but should be more stable for these use cases. To do this, open up BrowserNative.cs and find where
PROXY_BROWSER_API is defined. Add
UNITY_EDITOR_WIN to the list of conditions that trigger it and restart the Editor.
On OS X and Linux, the root Chromium process always runs outside the editor.
On builds, the root Chromium process always runs within your game for best performance.
- Delete all cookies with
- Grab the cookies from the browser with
browser.CookieManager.GetCookies(). This is asynchronous and returns a promise, see the promise section for more information on the promise library.
- Once you have a cookie, you can make edits and call
cookie.Update()or get rid of it with
- Create new cookies from scratch with
new Cookie(browsser.CookieManager)adjust the fields (be sure to set at least a domain, name, and value!) then create it with
- Aside from clearing all cookies, the Cookie API is a bit experimental, in particular, the dates may not function very well.
- You can customize which browser items the user is allowed to right-click (and get a context menu on). Look in the inspector under "Allow Context Menu On". By default, only text boxes will allow a context menu.
- By default, the
<body>of pages will be rendered as transparent. You can change to from fully transparent to any fully opaque color by changing the "Background Color" option in the inspector. The color must be changed before the first
- Custom mouse cursors are supported via CSS cursors.
- You can control what happens when navigation attempts to open a new window. Change
browser.newWindowActionto a value of your choice. If you'd like to allow opening new windows inside the game world, check out the NewWindow demo.
- We use a user agent that makes most websites think we're Chrome, but it does identify the engine, library, and your application's name and version. Change your application's name and version in the Player Settings. Restart the editor to see changes.
- You can force your own user agent by calling
UserAgent.SetUserAgent(string). This must be called before the first browser initializes. (In the Editor you must restart to see this change; it's immutable once the first browser initializes.)
- This system uses Chromium's separate process rendering architecture. It is normal to see one or more
ZFGameBrowserchild processes once a browser has been opened.
- A number of events, such as page load error, are available for you to hook into. Search Browser.cs for "public event" and read the documentation above each.
- Disabling the Browser MonoBehaviour will not stop the underlying browser from running. Destroy the object or load a blank page to free up resources a page is using.
- When a browser's image changes, we re-upload the texture to the GPU. Generating mipmaps is expensive, so the included prefabs turn off mipmap generation and use a special mipmap-emulating shader that "fakes" a texture with mipmaps, keeping ugly pixelation at bay for a minimal cost. Check out the Materials/EmulatedMipmap folder.
- You can adjust the command-line switches sent to Chromium by fiddling with
BrowserNative.commandLineSwitches. Read the comment above it in BrowserNative.cs for instructions.
The browser is rendered offscreen in a separate process and the resulting pixels are transferred to a texture. Performance will not be as good as native Chromium, but should be fine when using either small textures or minimal animation.
- All activity (mouse clicks, JS calls, input) is sent asynchronously to a separate renderer process and the results are asynchronously reported back. As such, there is a short delay between when a command is issued and when the results are visible. The delay should be quite reasonable in most cases, but don't expect results the same frame you issue a command.
- Avoid using a Browser for latency-critical use cases such as rhythm games, world-aligned HUD markers, and rendering mouse cursors.
- Try to use small (texture size) Browsers for animations and things that frequently update. Large sizes are more suitable for static displays and user interfaces.
- Frame updates for large (resolution) browsers are expensive. Often the final image is composited on the GPU, pulled back to the CPU, then pushed to the GPU again from a different process. Depending on the hardware, size of texture, and frequency of updates, this can impact framerates poorly.
- Remember that on almost all systems the browsers use the same GPU for rendering that Unity does. If you have heavy content, be sure to factor this into your rendering budget.
This version of ZFBrowser includes experimental support for Adobe Flash. Enabling it requires some extra steps.
The Web is an evolving place and ever-increasingly interactive web sties don't need Flash to support media-rich content.
You need Flash if you want to:
- Display content that is only available with Flash.
- Watch video that uses proprietary codecs, such as h.264. ZFBrowser doesn't have licenses for these codecs, but Flash does and many video streaming sites will fall back to using a Flash player to stream content if necessary.
If you are developing locally, prototyping, or will only distribute your application to computers that you control, use this method.
- Install the Adobe Flash Player on your system.
- Go to https://get.adobe.com/flashplayer/otherversions/
- Select your OS
- Select the latest "PPAPI" version available.
- Uncheck boxes for things you don't want.
- Download now.
- Install using the usual methods for your OS.
- Open up BrowserNative.cs
- Go! (You may need to restart the Editor.)
You'll need to install Flash on every computer you distribute your application to.
To distribute Flash with your application, you'll need to get permission from Adobe and run their installer with your installer.
General flow: Untested, let me know how it goes!
- Start development using the instructions in the last section, including the
- Get a distributor's license for your application
- Apply here
- Fill out paperwork, get approval from Adobe.
- Get an installer from Adobe. You need the PPAPI version (for Chromium).
- Set up the Flash installer to run when your application installs.
- Support for the inspector is experimental, it can be unstable at times.
- Support for Flash is experimental. Sometimes a command prompt window may flash while starting Flash content.
- On occasion the editor may crash/hang when closing/switching projects or opening pop-up windows.
- Build your complicated crafting UI in HTML
- Replace your HUD with a browser page
- Door access/control panels
- In-game billboard advertisements
Need help? https://zenfulcrum.com/contact