A Guide for Styling Unity Using WebGL Templates
Overview
For those who are unfamiliar with what a WebGL Template is, and how to implement it, they can read more in the Unity documentation here, or read more on this page for a brief overview.
WebGL Basics
When a WebGL project is built using Unity, the player is embedded in a basic HTML page to be displayed by a browser.
The basic HTML pages presented by Unity have minimal styling, and are often used purely for proof-of-concept purposes. The Table Realms WebGL template serves to embed the Unity projects in pages that are more relevant to the Table Realms theme, and are more aesthetically pleasing to users.
WebGL Template Folder Structure
Custom WebGL templates can be added to your Unity project by creating a folder called “WebGLTemplates” in the “Assets” folder. Once you have copied the Table Realms WebGL template to the folder, it will appear among the options on the Player Settings Inspector.
The following scripts and template tags are essential to the WebGL template, and should not be deleted from the source code:
- Script tag for the Unity WebGL loader:
<script src="%UNITY_WEBGL_LOADER_URL%"></script>
- Script for instantiating the game:
<script> var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%");</script>
- A
<div> tag, which id is used in the instantiation function. The contents of this div will be replaced with the game instance.
Table Realms WebGL Template Features
The Table Realms Unity WebGL template has several features, including:
- A custom Unity loading screen
- UI scaling and retina support
- Fullscreen compatibility
- Removal of unnecessary prompts
There are currently four custom JS scripts that run in the Table Realms WebGL template.
To learn more about each script, and its purpose, please expand the individual menu items below:
Progress.js
The purpose of this script is to create a loading spinner, rather than the standard Unity progress bar.
While the download of the Unity package is less than 90%, the message container displays “downloading”.
Once the download of the Unity package exceeds 90%, the message container changes to display “Preparing”.
function Progress(gameInstance, progress) {
this.message = "Loading...";
if (!gameInstance.Module)
return;
if (progress < 0.9) {
this.message = "Downloading";
}
if (progress >= 0.9) {
this.message = "Preparing";
document.getElementById("spinner").style.display = "inherit";
document.getElementById("bgBar").style.display = "none";
document.getElementById("progressBar").style.display = "none";
}
if (progress == "complete") {
document.getElementById("loadingBox").style.display = "none";
}
var length = 100 * Math.min(progress, 1);
bar = document.getElementById("progressBar")
bar.style.width = length + "%";
document.getElementById("loadingInfo").innerHTML = this.message;
};
RetinaSupport.js
The purpose of this script is to ensure the page scales correctly to the device screen, so that the players don’t have to scroll around the screen in order to play the games.
The script also disables the user scalability, so that they cannot accidentally zoom in and out while using the touch functionality.
var metaTag=document.createElement('meta');
metaTag.name = "viewport";
metaTag.content = "width=device-width, initial-scale=" + (1.0/window.devicePixelRatio).toString() + ", maximum-scale=1.0, user-scalable=0";
document.getElementsByTagName('head')[0].appendChild(metaTag);
TableRealmsStartup.js
The purpose of this script is to provide a state to the game when between the point of the webpage having loaded and the Unity player loading.
Once this executes, code is merged into the web page through the Table Realms Web Build plugin
var tableRealmsState="Waiting";
ToggleFullscreen.js
The purpose of this script is to provide the ability to toggle a full screen, borderless view in console mode.
The user can toggle fullscreen capabilities by clicking once on the console screen after the game has loaded.
var doc = document;
var docEl = doc.documentElement;
function requestFullscreen () {
var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen;
if(!doc.fullscreenElement && !doc.mozFullScreenElement && !doc.webkitFullscreenElement && !doc.msFullscreenElement) {
requestFullScreen.call(docEl);
}
}
function exitFullscreen () {
var cancelFullScreen = doc.exitFullscreen || doc.mozCancelFullScreen || doc.webkitExitFullscreen || doc.msExitFullscreen;
if(doc.fullscreenElement || doc.mozFullScreenElement || doc.webkitFullscreenElement || doc.msFullscreenElement) {
cancelFullScreen.call(doc);
}
}
window.onload=function(){
addFullscreenDiv();
if('onfullscreenchange' in document){
document.addEventListener('fullscreenchange', fullScreenHandler);
}
if('onmozfullscreenchange' in document){
document.addEventListener('mozfullscreenchange', fullScreenHandler);
}
if('onwebkitfullscreenchange' in document){
document.addEventListener('webkitfullscreenchange', fullScreenHandler);
}
if('onmsfullscreenchange' in document){
document.onmsfullscreenchange = fullScreenHandler;
}
function fullScreenHandler (event) {
if (document.webkitIsFullScreen == false ||
document.mozFullScreen == false) {
addFullscreenDiv();
}
}
function removeFullscreenDiv() {
var body = document.getElementsByTagName("BODY")[0];
body.removeChild(document.getElementById("fullScreenToggle").parentElement);
}
function addFullscreenDiv() {
// create fullscreen div
var div = document.createElement('div');
var body = document.getElementsByTagName("BODY")[0];
body.appendChild(div);
div.innerHTML = '<div id="fullScreenToggle"></div>';
// Add click event listener
div.addEventListener("click", function() {
requestFullscreen();
removeFullscreenDiv();
}, false);
}
}
Implementing the Table Realms Template Scripts
Once the scripts have been created properly, they can be implemented in the WebGL template’s Index.html file, as follows:
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>%UNITY_WEB_NAME%</title>
<link rel=icon href= "data/favicon.png">
<link rel="stylesheet" href="data/spinner.css">
<link rel="stylesheet" href="data/style.css">
<script src="%UNITY_WEBGL_LOADER_URL%"></script>
<!-- Our custom scripts are added here -->
<script src="js/TableRealmsStartup.js"></script>
<script src="js/ToggleFullscreen.js"></script>
<script src="js/RetinaSupport.js"></script>
<script src="js/Progress.js"></script>
<script>
// Load the unity player
var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%",
{
onProgress: Progress,
Module: {
// Set the cache request header
cacheControl: {"default": "max-age=86400"},
onRuntimeInitialized: function () {
Progress(gameInstance, "complete");
}
}
});
</script>
</head>
<body>
<!-- gameContainer is the div the canvas gets injected into-->
<div id="gameContainer"></div>
<!-- loaderContent is where our game icon, loading bar, spinner and status text lives-->
<div class="loaderContent">
<div id="loadingBox">
<!--Game icon-->
<img id ="loadingIcon" src="data/loaderImage.jpg">
<!--Spinner-->
<div id="spinner" class="lds-css ng-scope" style="display: none; margin: 0 auto">
<div class="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
</div>
<!--Progress bar-->
<div id="bgBar">
<div id="progressBar"></div>
</div>
<!--Status text-->
<p id="loadingInfo">Loading...</p>
</div>
</div>
</body>
</html>