Wednesday, January 25, 2023

Wednesday, December 14, 2022

Unity Addressable Assets in WebGL with Dynamic Remote Load Path

 We recently worked on a Unity WebGL project that used Addressable Assets, and it included a library that required us to load the Addressables from a Remote Load Path.  However, we knew we would be hosting the final Addressable Assets at the same location as the WebGL application itself, so they would always have the same base URL.  This location could change, though depending whether we were testing on a staging server or a live server, and we didn't want to remake the Unity build for each location we would be deploying to.

Originally, it seemed that we had to have a fixed Remote Load Path URL for the Unity build, and we created a Python script that would replace the path from Unity with a custom path depending on where we knew we were deploying to.  This proved cumbersome, though, and we found a better solution.

This Unity forum thread provides some helpful information about how to specify Addressable Assets paths with more dynamic information.  The Addressable Assets system allows you to specify variables in the build and load paths that will be evaluated at either build time or runtime.  Based on that and the fact we can look up the current location a web page is running from using window.location.href, we can dynamically generate a Remote Load Path for our Addressables.

First, we create a MonoBehaviour to handle the dynamic path.  This is necessary in order to access it through Javascript at runtime.

using UnityEngine;

public class CustomAddressablePaths : MonoBehaviour
{
     public static string RemoteURL
     {
          if ( _instance != null )
          {
               if ( _instance.remoteURL.EndsWith( "/" ) )
               {
                    return _instance.remoteURL + "ServerData";
               }

               return _instance.remoteURL + "/ServerData";
          }

          return "";
     }

     private static CustomAddressablePaths _instance = null;

     private string remoteURL = "";

     private void Awake()
     {
          if ( _instance == null )
          {
               _instance = this;
          }
          else if ( _instance != this )
          {
               Destroy( gameObject );

               return;
          }

          DontDestroyOnLoad( gameObject );
     }

     public void SetRemoteURL( string remoteURL )
     {
          this.remoteURL = remoteURL;
     }
}

Now, in the Remote Load Path in the Addressables Profile, we can use the {} syntax to specify a runtime value of {CustomAddressablePaths.RemoteURL}.


In the startup scene of the project, create a new GameObject named CustomAddressablePaths and add the CustomAddressablePaths component.  In theory this should be set to exist before the Addressables system is initialized.

If you're not already using a custom WebGL template for the project, we can create a new one.  Copy the contents of <Unity Editor install path>\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\WebGLTemplates\Default to your project under Assets\WebGLTemplates.  Give it a new subfolder name (e.g. Assets\WebGLTemplates\MyNewTemplate).  Select the new template from the WebGL PlayerSettings "Resolution and Presentation" section.

In index.html in the custom WebGL template, find where createUnityInstance() is run, and where a variable called unityInstance is returned.  You can then run the following Javascript code:

unityInstance.SendMessage( "CustomAddressablePaths", "SetRemoteURL", window.location.href );


Finally, when deploying your WebGL game, assuming your index.html file is at <server root>\index.html, the built Addressable Assets should be at <server root>\ServerData.  Now when the Addressables system attempts to download an asset, it should use the correct URL.

Friday, December 9, 2022

Terror of Hemasaurus!

What could be worse than a rampaging pixel-dinosaur annihilating everything in its path?  Four of them, of course!  Break out your extra controllers and join in four-player couch coop as you take humanity to task for its environmental sins!  Topple physics-simulated buildings, kick cars into helicopters, then throw the helicopters into hydrogen-filled blimps!


We helped bring Terror of Hemasaurus to Xbox One, PS4, and (once mid-January rolls around) Switch!


Thursday, November 3, 2022

Ghost Song!

A loving modern homage to Metroid, Ghost Song features lovingly rendered 2D artwork and backgrounds with incredible layers of detail and depth.  You're challenged to explore the desolate environments of the moon Lorian, finding new paths and new abilities and discovering its buried secrets.


Ghost Song is built with Unity, and we worked with the original developer and Humble Bundle to achievement major performance improvements, and to make it available on all major platforms simultaneously.  Get it on Xbox, PS4 & PS5, Switch, Steam, and a variety of other storefronts.

Tuesday, October 11, 2022

Eville!

Eville is a multiplayer social-deduction game, built using the Unreal engine.  You find yourself in a village riddled by a series of murders. Some say it might have been you - or was it? Convince others you're not the perpetrator to stay alive, or use the unique abilities of your class to misdirect the investigation.


We helped bring Eville to multiple consoles.  Now available on Steam and Xbox Gamepass, with full cross-play support!

Wednesday, July 20, 2022

Severed Steel!

Severed Steel is a single-player Unreal-based FPS featuring a fluid stunt system, destructible voxel environments, loads of bullet time, and a unique one-armed protagonist. It's you, your trigger finger, and a steel-toed boot against a superstructure full of bad guys. Chain together wall runs, dives, flips, and slides to take every last enemy down.


We helped bring Severed Steel to PlayStation, Xbox, and Switch!