CODE SPHERE TUTORIALS
Note that adding Firebase to your Unity project involves tasks both in the Firebase console and in your open Unity project (for example, you download Firebase config files from the console, then move them into your Unity project).
Create a Database
If you haven't already, create a Firebase project: In the Firebase console, click Add project, then follow the on-screen instructions to create a Firebase project or to add Firebase services to an existing GCP project.
Navigate to the Database section of the Firebase console. You'll be prompted to select an existing Firebase project. Follow the database creation workflow.
Select a starting mode for your Firebase Security Rules:
- Test mode
Good for getting started with the mobile and web client libraries, but allows anyone to read and overwrite your data. After testing, make sure to review the Understand Firebase Realtime Database Rules section.
To get started with the web, iOS, or Android SDK, select test mode.
- Locked mode
Denies all reads and writes from mobile and web clients. Your authenticated application servers can still access your database.
Click Done.
When you enable Realtime Database, it also enables the API in the Cloud API Manager.
Setting up public access
The Realtime Database provides a declarative rules language that allows you to define how your data should be structured, how it should be indexed, and when your data can be read from and written to. By default, read and write access to your database is restricted so only authenticated users can read or write data. To get started without setting up Authentication, you can configure your rules for public access. This does make your database open to anyone, even people not using your app, so be sure to restrict your database again when you set up authentication.
Configuring the SDK for the Unity Editor.
When testing your scene in the Unity Editor, you can use the Realtime Database. You must configure the SDK with the proper database URL. Call SetEditorDatabaseUrl with the url of your database.
Structure Your Database
Before you begin
Before you can use Realtime Database, you need to:
Register your Unity project and configure it to use Firebase.
If your Unity project already uses Firebase, then it's already registered and configured for Firebase.
If you don't have a Unity project, you can download a sample app.
Add the Firebase Unity SDK (specifically,
FirebaseDatabase.unitypackage
) to your Unity project.
Note that adding Firebase to your Unity project involves tasks both in the Firebase console and in your open Unity project (for example, you download Firebase config files from the console, then move them into your Unity project).
Structuring Data
This guide covers some of the key concepts in data architecture and best practices for structuring the JSON data in your Firebase Realtime Database.
Building a properly structured database requires quite a bit of forethought. Most importantly, you need to plan for how data is going to be saved and later retrieved to make that process as easy as possible.
How data is structured: it's a JSON tree
All Firebase Realtime Database data is stored as JSON objects. You can think of the database as a cloud-hosted JSON tree. Unlike a SQL database, there are no tables or records. When you add data to the JSON tree, it becomes a node in the existing JSON structure with an associated key. You can provide your own keys, such as user IDs or semantic names, or they can be provided for you using the Push()
method.
Although the database uses a JSON tree, data stored in the database can be represented as certain native types that correspond to available JSON types to help you write more maintainable code.
Best practices for data structure
Avoid nesting data
Because the Firebase Realtime Database allows nesting data up to 32 levels deep, you might be tempted to think that this should be the default structure. However, when you fetch data at a location in your database, you also retrieve all of its child nodes. In addition, when you grant someone read or write access at a node in your database, you also grant them access to all data under that node. Therefore, in practice, it's best to keep your data structure as flat as possible.
Create data that scales
When building apps, it's often better to download a subset of a list. This is particularly common if the list contains thousands of records. When this relationship is static and one-directional, you can simply nest the child objects under the parent.
Sometimes, this relationship is more dynamic, or it may be necessary to denormalize this data. Many times you can denormalize the data by using a query to retrieve a subset of the data, as discussed in Retrieve Data.
But even this may be insufficient. Consider, for example, a two-way relationship between users and groups. Users can belong to a group, and groups comprise a list of users. When it comes time to decide which groups a user belongs to, things get complicated.
Write, update, or delete data at a reference
Basic write operations
For basic write operations, you can use SetValueAsync()
to save data to a specified reference, replacing any existing data at that path. You can use this method to pass types that correspond to the available JSON types as follows:
string
long
double
bool
Dictionary<string, Object>
List<Object>
Append to a list of data
Use the Push()
method to append data to a list in multiuser applications. The Push()
method generates a unique key every time a new child is added to the specified Firebase reference. By using these auto-generated keys for each new element in the list, several clients can add children to the same location at the same time without write conflicts. The unique key generated by Push()
is based on a timestamp, so list items are automatically ordered chronologically.
You can use the reference to the new data returned by the Push()
method to get the value of the child's auto-generated key or set data for the child. Calling Key
on a Push()
reference returns the value of the auto-generated key.
Update specific fields
To simultaneously write to specific children of a node without overwriting other child nodes, use the UpdateChildrenAsync()
method.
Delete data
The simplest way to delete data is to call RemoveValue()
on a reference to the location of that data.
You can also delete by specifying null
as the value for another write operation such as SetValueAsync()
or UpdateChildrenAsync()
. You can use this technique with UpdateChildrenAsync()
to delete multiple children in a single API call.
Know when your data is committed.
To know when your data is committed to the Firebase Realtime Database server, you can add a continuation. Both SetValueAsync()
and UpdateChildrenAsync()
return a Task
that allows you to know when the operation is complete. If the call is unsuccessful for any reason, the Tasks IsFaulted
will be true with the Exception
property indicating why the failure occurred.
Save data as transactions
When working with data that could be corrupted by concurrent modifications, such as incremental counters, you can use a transaction operation. You give this operation a Func
. This update Func
takes the current state of the data as an argument and returns the new desired state you would like to write. If another client writes to the location before your new value is successfully written, your update function is called again with the new current value, and the write is retried.
Write data offline
If a client loses its network connection, your app will continue functioning correctly.
Every client connected to a Firebase database maintains its own internal version of any active data. When data is written, it's written to this local version first. The Firebase client then synchronizes that data with the remote database servers and with other clients on a "best-effort" basis.
As a result, all writes to the database trigger local events immediately, before any data is written to the server. This means your app remains responsive regardless of network latency or connectivity.
Once connectivity is reestablished, your app receives the appropriate set of events so that the client syncs with the current server state, without having to write any custom code.
0 Comments