Firebase with Unity (even in WebGL Build!)

Leonardo Tórtoro Pereira
Firebase Developers
12 min readJun 10, 2022
Photo by Element5 Digital on Unsplash

Introduction

Salutations! If you are here, you’re probably interested in adding some Firebase functionalities to your Unity project, right? That was what I wanted!

Firebase is HUGE and its free tier is enough for many indie and research projects. There are many cloud database products, the analytics side, the server… This isn’t a full guide to Firebase applications in Unity (at least not yet… Maybe in some months…). But, Firebase’s Youtube has some nice videos about it. And there are some awesome tutorials over the internet, like this one for Analytics events usage.

This is about setting things up for every Unity build type and testing with a simple Hosting and Firestore usage.

We will host our WebGL build and collect some gameplay data, saving in a Firestore database. However, we will also learn how to collect this data to Firestore even for desktop or mobile builds (as it’s much easier and the project will be ready for it anyway).

Motivation

I’m using this specific WebGL setup to conduct anonymous experiments with players for my PhD using Artificial Intelligence to generate procedural contents for my game prototype. So, to get as many people as possible to play the game, it’s very important for me to host it as a web game (people tend to get lazy when it comes to downloading simple games, specially if they have to answer some questionnaires later).

We were previously hosting our own server in our university’s machine… But here in Brazil we don’t get much funding nowadays, specially when researching on games. So, our machine was super slow and it became impossible to host the game there. Firebase saved us! And now I hope this tutorial will help anybody else that may want to use it with a WebGL build like us! Enough chit-chat, let’s get to the point!

Installing Firebase and Hosting the WebGL Build

We will get the hosting part done first, as it’s easier!

Create the Firebase Project

The first step is to create a Firebase project and register a Web app in your project (the first step only). This is enough to host the build there. Also, this will also get basic analytics data if you allow the project to use it!

Test and Deploy

Now, we will send the project from your computer to the cloud! Install the Firebase CLI, login (firebase login), test (firebase projects:list) and, if everything is ok, you can initialize your project with the hosting functionality: firebase init hosting. Remember to run the Firebase Client in the folder where your WebGL build is! You can test locally using firebase serve --only hosting, and, if everything is ok, send it to the cloud by using firebase deploy. For other uses, check the Firebase CLI documentation. If all goes well, your folder should look like this:

A directory with a Unity WebGL build and everything initialize to host it via Firebase. Bonus: The Firebase CLI.exe

And you can check the Hosting page in you Firebase console and see something like this:

The hosting tab in your Firebase console after deploying your WebGL build should look something like this!

Aaaaand it’s done! Congrats! Your WebGL game is now on the cloud for anyone to play (or… you could upload it to itch.io, which is awesome!

Now, a little example on a JSON file with the player’s data in Unity, and then, back to our Firebase usage!

An example in Unity using the 2D Platformer Microgame

I’ve create a toy project as an example of a simple application using Firebase’s Firestore both for Desktop and WebGL and will use most of the new code as example for the rest of this guide. You can check the project here in GitHub. And test the WebGL version here.

In this project, we created 3 new scripts to handle the player data, manipulate Firebase and display the data in the UI. For the player data, the PlayerData.cs script has the following variables:

We will collect the above data from the player, as in our PlayerData.cs script.

As the WebGL build will use the JavaScript version of Firebase, while the other versions use the Firebase API, we must use some compiler flags to handle both situations. For everything except the WebGL build, you can use the Firestore’s API commands to identify your properties as those that will be serialized to Firestore. Use the FirestoreProperty()and, in our case, we will name it with the variable’s name, passing it as a string.

We do so because for the WebGL the serialization must be done without the API and the variable’s name instead of the property will be used. If the Property itself was serialized (via the field:SerializedFieldcommand in an auto-property), the WebGL’s generated data would have the info about the backing field “k__BackingField”. Another option is to rename the property name via Newtonsoft’s [JsonProperty(PropertyName = "name")].

Just remember to serialize everything you want to be on the database and we should be done!

Saving this as a JSON file is very easy! You can use Newtonsoft’s Json.NET framework, or the native JsonUtility from Unity. For the latter, considering an instance of PlayerData called playerData, we just use JsonUtility.ToJson(CurrentPlayer) and it gives us a string with the object converted into Json format.

We will check the other scripts and any other changes in the original Unity’s project later, according to our needs. Let’s see how to use Firebase’s Firestore API to save and load players data from our game.

Firebase for Unity — Everything Except WebGL

Now, to add Firebase to your Unity project, there is something important to know: Firebase has official support for Android and iOS builds. There is a Beta desktop workflow that works in the IDE, Windows, macOS and Linux, but has limited support and is not intended for shipping (according to the Firebase website). As we already spoiled, there is a way to also use Firebase with WebGL, but it’s not officially supported and it’s tricky. We discuss it in the next section.

For all the intended builds, just follow the instructions from here:

Set a Unity workflow in Firebase project

Go to the project we already created, and now set a Unity workflow instead of the Web one. You can select an Android or iOS project (or both). Just get the data from the apps’ name from Unity player settings for each app and register. For the desktop, select one of them, doesn’t matter which

Add the Configuration files to your Unity project

Then, get the Firebase configuration files (a json for Android and a plist for iOS) and add this file anywhere under the Assets folder from your Unity project (maybe Assets/Data to tidy things up). Do it even if you want to use it for the desktop

  • If you are going for the desktop version, after adding the file, you must make sure your project is aimed to build for a desktop application (windows, linux or macOS, make sure it’s not set for WebGL or any other) and try to run the project from the Editor. It should create a file in the “Assets/StreamingAssets” path, name “google-services-desktop”. *If no file is created (even after refreshing with Ctrl+R), try closing and opening Unity again. The file should be there now.

Adding the Firebase Unity SDK

Now, we must get the Firebase Unity SDK. You can get a .zip with all of them from the Firebase console or here. Open your Unity project and then execute the files for each package you’d like to install. Then, just follow the importer commands.

For this project here, we’ll use the Firestore package (and the External Dependency Manager, Firebase App and Authentication, which are dependencies)

Example — Saving Player Data to Firestore!

Now, a quick example to show its usage via the Editor: We will save our previous PlayerData as a Json in the Firestore! I have changed a little the game’s original code to use each important event to record data from the player. The game uses a kind of Model-View-Controller (MVC) architecture. Meaning that all shared data will be in the Model/PlatformerModel.cs, most of the control will be in GameController.cs and PlayerController.cs.

For brevity’s sake I won’t go into the details of the game itself. But I’ve added a PlayerData.cs object inside PlatformerModel.cs’s end: public PlayerData CurrentPlayerData{get; set;}. Now, we can access the data and increment the counters at each important event.

The system uses and Event Polling design to handle every event and execute them in an organized way. So, every important event already has a common signature: they inherit from Simulation.Event.cs and have an Execute method, that is what will be executed when the given event happens. Usually, each of these events class have a call for the Singleton of the PlatformerModel PlatformerModel model = Simulation.GetModel<PlatformerModel>(). If it does not have, add it to update the player data.

For example, in the EnemyDeath.cs we add the following line inside the Execute method: model.CurrentPlayerData.IncrementKills(). I did something similar for the events of collecting tokens, completing the stage and the player dying.

Then, after you have set all data to a playerData object and want to save this player’s data in your Firestore (in our case, when they die or complete the level), just create a DocumentReference to your new (or old, it will create a new one if none exists) Document inside the desired Collection (here, the “gameplay” collection). And use the “SetAsync” method from the DocumentReference, passing the playerData object and calling the “ContinueWithOnMainThread”. No need to even use the Json stuff here!

FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
DocumentReference docRef = db.Collection("gameplay").Document(PlayerId.ToString());
docRef.SetAsync(this).ContinueWithOnMainThread(task => { });

If all goes well, you should see something like this at your Firebase Console’s Firestore Database tab:

The Firestore Database tab in your Firebase Console should now show the added collection and document.

*If you see a message like this: “Database URL not set in the Firebase config.” your config file (the google-servies.json or the plist) may have been generated before you’ve setup the Firebase (or other services) you wanted to use. Create them, re-download the config, replace the old one and, if using Desktop version, also delete the one generated in StreammingAssets.

And that’s it for the basics! You should now be ready to continue adding the other Firebase functionalities using the documentation from Firebase’s website. Now… for the hard part!

Getting data from Firestore and showing in a UI

To get data from the Firestore we can use the following code:

This code gets the data for all players in your Firestore “gameplay” Collection and adds them to a UI element to display

In the code above we make a Query to get all Documents inside the gameplay Collection. We tranform them to a Dictionary of “Document Id” and the content itself. To show in Unity, I’ve made a small UI scene that is loaded in an additive way to the scene. This UI has a Game Object prefab of an item and we instantiate a new item for every record, and set its text to the text created from all the data of a single player.

The menu itens’ script is PlayerDataItemUI.cs and the scene is PlayerDataScene. The result is a scene like this when you press the “Escape” button inside the game:

In-game scene of the menu showing data from different players.
  • In the WebGL version, this menu is a little broken. I’ll try fixing it later. Anchoring UI stuff in Unity for responsive screens is always a chore.

Firebase for Unity — WebGL

Ok, here goes the hard part! First of all, I only made it work thanks to @rotolonico’s FirebaseWebGL Unity package. Thanks for this! It seems there are some compatibility issues according to each Unity version you are using. I made it work for 2021.3.0f1!

It basically uses the Firebase Javascript SDK, creating a bridge between the webgl Javascript’s and your C# code.

Install the Package

Install the FirebaseWebGL package into your Unity

Call the SDK methods inside Unity

Call the Firebase Javascript SDK functions from the FirebaseBridge.cs class

In our example, after you have set all data to a playerData object and want to save this player’s data in your Firestore, just transform it into a Json and add it as a document. In the example below, we add it to a collection called “gameplay”, then pass the jsonData String (the data to be saved), the name of the new document (the player id), and the callback and fallback messages necessary for the method.

String jsonData = JsonUtility.ToJson(this);
FirebaseWebGLBridge.FirebaseFirestore.AddDocument("gameplay", jsonData, PlayerId.ToString(), "DisplayInfo", "DisplayErrorObject");

We can’t use the [FirestoreData] tags from before, so we must convert to Json! But still pretty simple, right?

To get the data it’s a little bit trickier. I ahd to change the script that bridges the C# methods and the JS ones called from the Firestore’s Web API. In FirebaseWebGL/Plugins/firebasefirestore.jslib we will change a little the GetDocumentsInCollection fuction. Instead of creating a dictionary for each data in the collection, we will create an array. Change the code inside the firebase.firestore().collection(parsedPath).get().then(function (quesrySnapshot){ to this:

var docs = [];
querySnapshot.forEach(function(doc) {
docs.push(doc.data());
});

This will make it easier to extract the class data from the json-like string it returns. Getting the Dictionary data back from this string is complicated with Newtonsoft’s package, so the array helps.

Details of how these scripts work and how they communicate between C# and JS can be seen in @rotolonico’s excellent video about the package.

Now, we will create the C# method that will call this bridge-like method: FirebaseWebGLBridge.FirebaseFirestore.GetDocumentsInCollection("gameplay", gameObject.name, "OnRequestSuccess", "DisplayErrorObject")

This is the method equivalent to the Firebase API’s to get all contents from the “gameplay” Collection and return it to the Game Object that called this and return the data via the “OnRequestSuccess” method.

This method is implemented by us, here:

public void OnRequestSuccess(string data)
{
Debug.Log("Data: "+data);
var parsedData = JsonConvert.DeserializeObject<List<PlayerData>>(data);
foreach (var player in parsedData)
{
Debug.Log("Player Data"+ player);
var newItem = Instantiate(playerListItemPrefab, playerListPrefab.transform);
newItem.GetComponent<PlayerDataItemUI>().DataText = player.ToString();
}
}

It will convert the data into a list of PlayerData objects and for each will create a new item for the menu.

Create the WebGL Build

Now, create the WebGL build! We need to change the index… But, you may need to do some updates for the newest versions of Unity (apparently, 2020 and newer).

  • First, you may need to change all the “SendMessage” methods form the .jslib files. They are inside the “Plugins” folder from the FirebaseWebGL package. Probably in the “Assets/FirebaseWebGL/Plugins” folder. Use some replacement method in your IDE (probably Ctrl+Shift+H) to change every “unityInstance.Module.SendMessage” to “window.unityInstance.SendMessage
  • While you’re at it, the .jslib files use a deprecated method “Pointer_stringify()”, you may want to change them to “UTF8ToString()” to avoid errors in the WebGL build.
  • Many browsers (specially Google Chrome) are having a hard time dealing with the Gzip compression. I had to change the build settings to uncompressed (Edit->Project Settings -> Player tab -> WebGL icon -> Publishing Settings tab -> Compression Format -> Disabled. Maybe it works for other browsers, but i did not test yet.

Add Firebase configuration and dependencies in index.html

Ok, this part gets delicate… You must add the Firebase app configuration to the index.html, but this has been changing at Unity’s and Firebase’s updates. The Step 1from this setup may work… or following the step-by-step from @rotolonico’s excellent video about the package! but it didn’t work for me! The “modular” version from the SDK version 9 was not working. I had to use this “compat” version that works as a compatibility mode. So, go get the Script from the Step 1, and add it to the bottom of your “index.html”, just before closing the </body> part. I had to change some parts, it ended up like this:

You must add this right before the end of the index.html body (</body>) and add your Firebase configuration.

Import the Firebase libraries to index.html

Now, get the “import” command for each library you use in your code from here. Again, the v9 format (import {} XXXX) did not work for me. I had to use the v8 version method, but adding the v9. So, above the previous <script> add them. My final version of the index.html added part was like this:

You must add the imports above the <script> added in the previous image.

Get the Unity Instance inside index.html

Last, but not least, there is another modification in the index.html for newer SDK versions. Right after the “createUnityInstance(…).then((unityInstance)= > { …” part, you must add this window.unityInstance = unityInstance; line. Like this:

Inside your index.html you should find this block of code. Just add the part to get unityInstance.

Ok, things should be working now. Try hosting a local server like we’ve seen before and test. It should save data in your Firestore like before:

Player data stored in the Firestore console tab.

If anything goes wrong, try checking if the other linked approaches work, depending on your Unity’s version. It took me a long trial and error session. Check the highlighted comment for @rotolonico’s video, and these issues. It may help!

Extra — Handling Both Cases

If you want you code to handle both the WebGL’s Firebase functions and the non-WebGL ones, just use the #if !UNITY_WEBGL directive for every Firebase SDKs method in the code, and #if UNITY_WEBGL for the methods from the FirebaseWebGL package. We already saw the snippet for the data. Now for both saving and loading the data from Firestore:

Adding the flag separates the method that uses the Firebase SDK in Unity and the method using the FirebaseWebGL package. This is the code to send data for the Collection. In the GitHub project is inside PlayerData.cs
Adding the flag separates the method that uses the Firebase SDK in Unity and the method using the FirebaseWebGL package. This is the code to get data from the Collection. In the GitHub project is inside FirebaseManager.cs

And your code should be ready to support every build type!

I hope this tutorial helps everyone that wants to use Firebase in Unity. Specially with WebGL builds! Be sure to check the whole project in GitHub to change the other data.

The classes you should look for changes are:

  • Bridging Firebase
    - FirebaseWebGL/Plugins/firebasefirestore.jslib
  • Everything under Scripts/Firebase
  • Updating player data in the Events:
    - Gameplay/EnemyDeath.cs
    - Gameplay/PlayerDeath.cs
    - Gameplay/PlayerEnteredVictoryZone.cs
    - Gameplay/PlayerTokenCollision.cs
  • Mechanics/PlayerController.cs (a quick fix to load the data in the additive scene)
  • Model/PlatformerModel.cs (adding PlayerData)

Thank you for the read :)

--

--

Leonardo Tórtoro Pereira
Firebase Developers

PhD Candidate in Computer Science and Mathematics, currently researching Procedural Content Generation in games. Game Development enthusiast.