Firebase Backend
Setup & Run Guide
Scope β This document explains how to integrate the BulletHellβ―Elementalβ―Templateβ―v1.4 with Firebase Authentication and Cloudβ―Firestore. It covers both a Quickβ―Start for experienced users and a StepβbyβStep walkthrough with screenshots for newcomers.
Read the offline backend page first
1. Quick Start (Experienced Users)
Unity Version β 2022.3β―LTS (or newer).
Packages β Ensure the following Unity packages are installed via Package Manager:
Input System
AI Navigation
InβApp Purchasing
2D Sprite
TextMeshPro (TMP)
Firebase SDK β Import:
FirebaseAuth 12.2.0(or newer)FirebaseFirestore 12.2.0(or newer)add FIREBASE in Scripting Define Symbols in Build Settings > Player
Template β Import BulletHellβ―Elementalβ―Template.
Scenes β Add to Build Settings in this order:
Login,Home, other maps.Tags / Layers β If missing, add Monster tag and assign it to all enemy prefabs.
googleβservices.json β Download from the Firebase Console and place inside Assets/StreamingAssets/ (create the folder if missing). Name must remain unchanged.
Firebase Console
Enable Email/Password and Anonymous signβin in Authentication β Signβin method.
Create Firestore collection Players.
Create rootβlevel collection BattlePass with
Document ID:
SeasonInfoField
Season(Number β 1)Field
StartSeason(Timestamp β season start date)
Apply the security rules shown below.
Run β Press Play in the
Loginscene. Account creation & data sync occur automatically.
Firestore Database Rules :
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
/* βββββββββ helper predicates βββββββββ */
function isSignedIn() { return request.auth != null; }
function isOwner(uid) { return isSignedIn() && request.auth.uid == uid; }
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
match /Players/{uid} {
/* READ (single doc + queries/collections) */
allow get, list: if isSignedIn();
/* WRITE (create/update/delete) β owner only */
allow create, update, delete: if isOwner(uid);
/* Inventory sub-collection */
match /PurchasedItems/Items/List/{itemId} {
allow get, list, create, update, delete: if isOwner(uid);
}
/* Catch-all for nested docs (Characters, Progress, β¦) */
match /{document=**} {
allow get, list, create, update, delete: if isOwner(uid);
}
}
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* GLOBAL NICKNAME REGISTRY (/PlayerNames/{nameLower})
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /PlayerNames/{nameLower} {
allow get: if true;
allow list: if false;
allow create: if isSignedIn()
&& request.resource.data.keys().hasOnly(['ownerUid','createdAt'])
&& request.resource.data.ownerUid == request.auth.uid;
allow update, delete: if isSignedIn()
&& resource.data.ownerUid == request.auth.uid
&& request.resource.data == resource.data;
}
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* CURRENCIES (/Players/{uid}/Currencies/{coinId})
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /Players/{uid}/Currencies/{coinId} {
allow get: if isOwner(uid);
allow list: if false;
allow delete: if false;
allow create: if isOwner(uid)
&& request.resource.data.keys().hasOnly(['initialAmount','amount'])
&& request.resource.data.initialAmount is int
&& request.resource.data.amount is int
&& request.resource.data.initialAmount >= 0
&& request.resource.data.amount >= 0;
allow update: if isOwner(uid)
&& request.resource.data.keys().hasOnly(['amount'])
&& request.resource.data.amount is int
&& request.resource.data.amount >= 0;
}
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* BATTLE-PASS META (/BattlePass/SeasonInfo)
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /BattlePass/{docId} {
allow get: if isSignedIn() && docId == "SeasonInfo";
allow list, create, update, delete: if false;
}
}
}
For developers who have not yet set up a project with Firebase or who have any questions, below is a detailed step-by-step guide with images:
2. StepβbyβStep Guide (With Images)
2.1 Create a URP Project
Open Unity Hub β New Project.
Select Universal 3D (URP) template.
Name your project and click Create.
Optional β HDRP/Builtβin pipelines work, but demo textures may need conversion.

2.2 Install Required Unity Packages
Window β Package Manager β Unity Registry. Add Input System, AI Navigation, InβApp Purchasing, 2D Sprite, TextMeshPro.

2.3 Import Firebase SDK
Download
FirebaseAuth.unitypackageandFirebaseFirestore.unitypackagefrom the Firebase Unity SDK Archive.Doubleβclick each package to import.
When prompted, allow ExternalDependancyManager to resolve libraries.
add FIREBASE in Scripting Define Symbols in Build Settings > Player

2.4 Import the Template
Drag the BulletHellβ―Elementalβ―Template .unitypackage into the Editor or install via Package Manager β My Assets.
2.5 Configure Project Settings
Player Settings β Identification β Package Name must match the Android/iOS package names you register in Firebase.
Switch Platform to Android or iOS before building (Editor β File β Build Settings).
2.6 Firebase Console Configuration
Create Project β add Android and/or iOS app with the correct package name.
Download googleβservices.json (Android) or GoogleServiceβInfo.plist (iOS).
Place json file in Assets/StreamingAssets/. If Unity cannot locate the file, verify the folder name and that the filename has no suffix (e.g., (1)).




Firestore Database β Start in production mode.
Create Collection
Playersβ add a dummy document (ID can be autoβgenerated).Create Collection
BattlePassβ new documentSeasonInfo.Add Number field
Season = 1.Add Timestamp field
StartSeason = <TODAY>.
Apply the security rules (see Quick Start above).
2.8 Prepare Cloud Firestore
Authentication β Signβin method: enable Email/Password and Anonymous.
2.7 Enable Authentication

2.8 Prepare Cloud Firestore
Firestore Database β Start in production mode.
Create Collection
Playersβ add a dummy document (ID can be autoβgenerated).Create Collection
BattlePassβ new documentSeasonInfo.Add Number field
Season = 1.Add Timestamp field
StartSeason = <TODAY>.
Apply the security rules (see Quick Start above).

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
/* βββββββββ helper predicates βββββββββ */
function isSignedIn() { return request.auth != null; }
function isOwner(uid) { return isSignedIn() && request.auth.uid == uid; }
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /Players/{uid} {
/* READ (single doc + queries/collections) */
allow get, list: if isSignedIn();
/* WRITE (create/update/delete) β owner only */
allow create, update, delete: if isOwner(uid);
/* Inventory sub-collection */
match /PurchasedItems/Items/List/{itemId} {
allow get, list, create, update, delete: if isOwner(uid);
}
/* Catch-all for nested docs (Characters, Progress, β¦) */
match /{document=**} {
allow get, list, create, update, delete: if isOwner(uid);
}
}
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* GLOBAL NICKNAME REGISTRY (/PlayerNames/{nameLower})
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /PlayerNames/{nameLower} {
allow get: if true;
allow list: if false;
allow create: if isSignedIn()
&& request.resource.data.keys().hasOnly(['ownerUid','createdAt'])
&& request.resource.data.ownerUid == request.auth.uid;
allow update, delete: if isSignedIn()
&& resource.data.ownerUid == request.auth.uid
&& request.resource.data == resource.data;
}
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* CURRENCIES (/Players/{uid}/Currencies/{coinId})
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /Players/{uid}/Currencies/{coinId} {
allow get: if isOwner(uid);
allow list: if false;
allow delete: if false;
allow create: if isOwner(uid)
&& request.resource.data.keys().hasOnly(['initialAmount','amount'])
&& request.resource.data.initialAmount is int
&& request.resource.data.amount is int
&& request.resource.data.initialAmount >= 0
&& request.resource.data.amount >= 0;
allow update: if isOwner(uid)
&& request.resource.data.keys().hasOnly(['amount'])
&& request.resource.data.amount is int
&& request.resource.data.amount >= 0;
}
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* BATTLE-PASS META (/BattlePass/SeasonInfo)
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
match /BattlePass/{docId} {
allow get: if isSignedIn() && docId == "SeasonInfo";
allow list, create, update, delete: if false;
}
}
}
2.9 Verify Tags, Layers & Scenes
If you imported the template into an existing project:
Add Monster tag in Edit β Project Settings β Tags & Layers.
Assign it to enemy prefabs in
BulletHellTemplate/Resources/Monsters/.Ensure scene order in Build Settings:
Login,Home, others.
2.10 Test in Editor
Open
Loginscene.Press Play β the template autoβcreates a local account, syncs with Firebase, and loads initial data.
Check Console for Firebase initialization logs.
3. Common Issues & Fixes
Issue
Cause
Fix
googleβservices.json not found
File in wrong location
Place inside Assets/StreamingAssets/. Refresh project.
"Unknown error" on account creation
Weak password
Use at least 8 chars, 1 number, 1 special char.
Android/iOS build fails on "Validate References"
Unused platform DLLs
Edit β Project Settings β Player β Other Settings, disable Validate References for unsupported platform.
4. Next Steps
Customize Battle Pass seasons by updating
SeasonandStartSeasonfields.Harden security with App Check or move save logic to Cloud Functions (requires paid Firebase plan).
Join our community for support and feature requests.
Discord β https://discord.com/invite/EGGj77g3eQ Email β rafbizachi5@gmail.com
Last updated