Firebase and Firestore
Firebase and Firestore
In this chapter we connect a Unity project to a Firebase project. We will use Cloud Firestore to store a small score document for an AR scene.
The example can:
- fetch a score document from Firestore
- write a score document to Firestore
- update the same document later
We use the Firestore REST API. This keeps the Unity setup small: no extra Unity Firebase SDK is needed for this first example.
Learning setup
The example below uses temporary open Firestore rules so you can focus on the Unity communication first. Never use open rules in a real app. For a real app, users should sign in and Firestore rules should check who is allowed to read and write.
Create the Firebase project
- Go to Firebase and sign in with a Google account.
- Open the Firebase console.
- Click Create a project.
- Give the project a clear name, for example
unity-ar-scoreboard. - Google Analytics is not required for this course, so you can disable it.
Enable Cloud Firestore
- In the Firebase console, open your project.
- Go to Build > Firestore Database.
- Click Create database.
- Choose Standard edition.
- Choose the closest region.
- Choose Start in test mode while developing.
- Create the database.
For this example we will use this Firestore structure:
arScores
team-demo
playerName: "Team demo"
score: 10
updatedAt: "2026-05-29T12:00:00Z"
Firestore rules for testing
Open the Rules tab in Firestore and use these rules while testing:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /arScores/{scoreId} {
allow read, write: if true;
}
}
}
Temporary only
These rules allow everyone to read and write the arScores collection. Use them only while learning. Replace them with authenticated rules before publishing an app.
Get the project id and API key
Unity needs two values to call Firestore:
- Project ID
- Web API key
Find them in Firebase:
- Open the Firebase project.
- Click the gear icon and open Project settings.
- Copy the Project ID.
- Scroll to Your apps.
- Add a Web app if you do not have one yet.
- Copy the Web API key from the Firebase config.
API key
The Firebase Web API key is not a password, but you should still restrict it in the Google Cloud Console for real apps. For this course example, we use it to identify the Firebase project from Unity.
Create the Unity scene
- Create a new empty GameObject in the Hierarchy.
- Name it
FirebaseManager. - Create a new folder
Scriptsin the Assets folder. - Create a new C# script named
FirestoreScoreClient. - Attach the script to the
FirebaseManagerGameObject.
FirestoreScoreClient script
Replace the content of FirestoreScoreClient.cs with this code:
using System;
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class FirestoreScoreClient : MonoBehaviour
{
[Header("Firebase")]
[SerializeField] private string projectId = "your-project-id";
[SerializeField] private string apiKey = "your-web-api-key";
[Header("Firestore document")]
[SerializeField] private string collection = "arScores";
[SerializeField] private string documentId = "team-demo";
[Header("Demo data")]
[SerializeField] private string playerName = "Team demo";
[SerializeField] private int score = 10;
private string DocumentUrl =>
$"https://firestore.googleapis.com/v1/projects/{projectId}/databases/(default)/documents/{collection}/{documentId}?key={apiKey}";
public void FetchScore()
{
StartCoroutine(FetchScoreRoutine());
}
public void SaveScore()
{
StartCoroutine(SaveScoreRoutine(playerName, score));
}
public void IncreaseScore()
{
score++;
StartCoroutine(SaveScoreRoutine(playerName, score));
}
private IEnumerator FetchScoreRoutine()
{
using UnityWebRequest request = UnityWebRequest.Get(DocumentUrl);
yield return request.SendWebRequest();
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"Firestore fetch failed: {request.error}\n{request.downloadHandler.text}");
yield break;
}
FirestoreDocument document = JsonUtility.FromJson<FirestoreDocument>(request.downloadHandler.text);
playerName = document.fields.playerName.stringValue;
score = int.Parse(document.fields.score.integerValue);
Debug.Log($"Fetched score: {playerName} has {score} points");
}
private IEnumerator SaveScoreRoutine(string newPlayerName, int newScore)
{
FirestoreDocument document = new FirestoreDocument
{
fields = new FirestoreFields
{
playerName = new FirestoreStringValue { stringValue = newPlayerName },
score = new FirestoreIntegerValue { integerValue = newScore.ToString() },
updatedAt = new FirestoreStringValue { stringValue = DateTime.UtcNow.ToString("O") }
}
};
string json = JsonUtility.ToJson(document);
byte[] body = Encoding.UTF8.GetBytes(json);
using UnityWebRequest request = new UnityWebRequest(DocumentUrl, "PATCH");
request.uploadHandler = new UploadHandlerRaw(body);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"Firestore save failed: {request.error}\n{request.downloadHandler.text}");
yield break;
}
Debug.Log($"Saved score: {newPlayerName} has {newScore} points");
}
}
[Serializable]
public class FirestoreDocument
{
public FirestoreFields fields;
}
[Serializable]
public class FirestoreFields
{
public FirestoreStringValue playerName;
public FirestoreIntegerValue score;
public FirestoreStringValue updatedAt;
}
[Serializable]
public class FirestoreStringValue
{
public string stringValue;
}
[Serializable]
public class FirestoreIntegerValue
{
public string integerValue;
}
Configure the script
- Select the
FirebaseManagerGameObject. - In the Inspector, fill in your Firebase Project ID.
- Fill in your Firebase Web API key.
- Keep the collection as
arScores. - Keep the document id as
team-demo. - Choose a player name and a starting score.
Inspector values
Because these fields use [SerializeField], you can change the values in the Unity Inspector without editing the C# script every time.
Add test buttons
For a quick test, add a small temporary UI with three buttons:
Fetch scoreSave scoreIncrease score
Create a Canvas and three Buttons. For each button:
- Select the button.
- Go to the On Click section.
- Click
+. - Drag the
FirebaseManagerGameObject into the object field. - Choose the matching method:
FirestoreScoreClient > FetchScoreFirestoreScoreClient > SaveScoreFirestoreScoreClient > IncreaseScore
Press Play and test the buttons. Open the Unity Console to see the debug messages. Also open Firestore in the Firebase console to see the document appear or update.
What the code does
The script calls this Firestore REST endpoint:
https://firestore.googleapis.com/v1/projects/{projectId}/databases/(default)/documents/arScores/team-demo
FetchScore uses UnityWebRequest.Get(...) to read the document.
SaveScore and IncreaseScore use a PATCH request. In Firestore, this creates the document if it does not exist yet, or updates the document if it already exists.
Firestore stores typed values. That is why the JSON contains fields like stringValue and integerValue:
{
"fields": {
"playerName": {
"stringValue": "Team demo"
},
"score": {
"integerValue": "10"
},
"updatedAt": {
"stringValue": "2026-05-29T12:00:00Z"
}
}
}
Use it in an AR scene
Once the basic communication works, you can call the same methods from AR events. For example:
- fetch the score when an image target is found
- increase the score when the player scans a correct target
- update Firestore when the AR task is completed
Exercise
Create a new document id for every team, for example team-1, team-2 and team-3. Let every team update only their own score document.