Throttling a Unity WebGL App

Sometimes, you may find that a WebGL app is taking up a lot of processing. While you’re browser may not show you exactly how much processing it’s talking, you’ll notice in the task manager that the process is taking up a lot more of the processor’s utilization when looking at your site and web app than before. While during active times, this is necessary because you can’t exactly have the game run for free (computationally) and the more intensive it is, it more it requires – or the slower it will run.

But what if you could detect at certain moments that it doesn’t need to run as fast? Maybe the user is scrolling around your website and have Javascript code to see that it’s scrolled out of view. What if you have many WebGL apps running simultaneously, and all together they take far more CPU resources than your users would prefer?

This post is going to cover the built-in WebGL modules to throttle the application. Note that I didn’t say suspend or pause, but throttle. The difference is that the application will still run, but it will run a lot slower and require less processor utilization.

Here’s the snippet showing the minimum amount of stuff needed to embed a game. Below that are two buttons that call the module functions we care about.

<!–– Unity WebGL utility classes ––>
<script src="/blog/content/WebHalt/TemplateData/UnityProgress.js"></script>
<script src="/blog/content/WebHalt/Build/UnityLoader.js"></script>

<!–– App DOM elements and game instancing ––>
<script>var gameInstance= UnityLoader.instantiate("gameInstance", "/blog/content/WebHalt/Build/WebHalt.json", {onProgress: UnityProgress});</script>

<div class="webgl-content">
   <div id="gameInstance" style="width: 600px; height: 600px">
</div>

<!–– Additional controls added to test Javascript Module functions ––>
<button style="width:600px;" onclick="gameInstance.Module.pauseMainLoop()">Pause</button>
<button style="width:600px;" onclick="gameInstance.Module.resumeMainLoop()">Resume</button>

If the Module member is new to you, in a nutshell it’s the interface to the Unity WebGL app’s web assembly. If that doesn’t mean anything to you, don’t worry, just notice there’s a pauseMainLoop() and resumeMainLoop() function provided for you in it. Here’s the snippet in action.

Yes, I know, I know, the function is called pauseMainLoop(). Why am I saying it’s not pausing? Well, because it’s not. While the app may initially halt, you’ll notice after a couple of seconds that it’s still running, just at a very low frame rate. And it’s still taking up noticeable processor resources, just significantly less.

My Metrics

When this simple app is running normally, task manager will tell me Chrome is using 4% – 10% processor utilization.
When the app is paused, task manager will well me Chrome is using 0.0% – 1.0% processor utilization.

Timing Observations

From observing it with the timing metrics, here’s what I can gathered/extrapolated from the app being throttled:

The app appears to update and render pretty close to 1 frame a second.

The deltaTime reports 0.1 and the Time.time grows at that speed. This means the apps perception of time is 10x slower than real time.

Coroutines are still rendered once per frame.

The number of fixed update calls per frame matches Time.fixedDeltaTime which didn’t change (it’s 0.02 no matter if the app is throttled or not). So fixed update – and probably physics – also run 10x slower than real time, but don’t suffer from (time resolution issues from) the deltaTime being forced to 0.1.

All this is briefed in Unity’s page on WebGL performance.

Throttling In-App

Unity’s page on WebGL performance also talks about throttling the application, except they talk doing it in the application itself by playing with Application.targetFrameRate. One thing to note is that without adding extra communication between the browser and app – this will be the default mode of operation for the application, and not event-driven – i.e. throttling when we detect it’s appropriate based on what the user is doing in the browser.

Information on the sample WebGL app can be found here.
Built with Unity 2018.3.8f1
Authored and tested in Chrome.
– Stay strong, code on. William Leu

More articles here. More articles about Unity WebGL here.