Saving Data in Unity3D Using Realm
Rate this tutorial
(Part 5 of the Persistence Comparison Series)
We started this tutorial series by looking at Unity and .NET native ways to persist data, like
File, and the
BinaryWriter. In the previous part, we then continued on to external libraries and with that, databases. We looked at ``SQLite` as one example.
First, here is an overview over the complete series:
Each part is sorted into a folder. The four scripts we will be looking at in this tutorial are in the
Realmsub folder. But first, let's look at the example game itself and what we have to prepare in Unity before we can jump into the actual coding.
Note that if you have worked through any of the other tutorials in this series, you can skip this section since we're using the same example for all parts of the series, so that it's easier to see the differences between the approaches.
The goal of this tutorial series is to show you a quick and easy way to make some first steps in the various ways to persist data in your game.
Therefore, the example we'll be using will be as simple as possible in the editor itself so that we can fully focus on the actual code we need to write.
A simple capsule in the scene will be used so that we can interact with a game object. We then register clicks on the capsule and persist the hit count.
When you open up a clean 3D template, all you need to do is choose
You can then add scripts to the capsule by activating it in the hierarchy and using
Add Componentin the inspector.
The scripts we will add to this capsule showcasing the different methods will all have the same basic structure that can be found in
The first thing we need to add is a counter for the clicks on the capsule (1). Add a
[SerilizeField]here so that you can observe it while clicking on the capsule in the Unity editor.
Whenever the game starts (2), we want to read the current hit count from the persistence and initialize
hitCountaccordingly (3). This is done in the
Start()method that is called whenever a scene is loaded for each game object this script is attached to.
The second part to this is saving changes, which we want to do whenever we register a mouse click. The Unity message for this is
OnMouseDown()(4). This method gets called every time the
GameObjectthat this script is attached to is clicked (with a left mouse click). In this case, we increment the
hitCount(5) which will eventually be saved by the various options shown in this tutorial series.
HitCount.csand ``RealmExampleSimple.cs` in the repository for the finished version.)
Now that you have seen the example and the increasing hit counter, the next step will be to actually persist it so that it's available the next time we start the game.
- Install with NPM
- Manually Install a Tarball
Let's choose option #1 for this tutorial. The first thing we need to do is to import the Realm framework into Unity using the project settings.
Package Manager→ cogwheel in the top right corner →
Advanced Project Settings:
Scoped Registries, you can add the
NPMas a source for libraries. The final step is to tell the project which dependencies to actually integrate into the project. This is done in the
manifest.jsonfile which is located in the
Packagesfolder of your project.
Here you need to add the following line to the
manifest.jsonshould look something like this:
When you switch back to Unity, it will reload the dependencies. If you then open the
Package Manageragain, you should see
Realmas a new entry in the list on the left:
We can now start using Realm in our Unity project.
Similar to other databases, we need to start by telling the Realm SDK how our database structure is supposed to look like. We have seen this in the previous tutorial with SQL, where we had to define tables and column for each class we want to save.
With Realm, this is a lot easier. We can just define in our code by adding some additional information to let know Realm how to read that code.
Look at the following definition of
HitCount. You will notice that the super class for this one is
RealmObject(1). When starting your game, Realm will automatically look for all sub classes of
RealmObjectand know that it needs to be prepared to persist this kind of data. This is all you need to do to get started when defining a new class. One additional thing we will do here, though, is to define which of the properties is the primary key. We will see why later. Do this by adding the attribute
With our data structure defined, we can now look at what we have to do to elevate our example game so that it persists data using Realm. Starting with the
HitCountExample.csas the blueprint, we create a new file
First, we'll add two more fields —
hitCount— and rename the
hitCounterto avoid any name conflicts:
Those two additional fields will let us make sure we reuse the same realm for load and save. The same holds true for the
HitCountobject we need to create when starting the scene. To do this, substitute the
Start()method with the following:
A new Realm is created by calling
Realm.GetInstance()(1). We can then use this
realmobject to handle all operations we need in this example. Start by searching for an already existing
Find<>function (2) that let's you search for a specific class that was defined before. Additionally, we can pass long a primary key we want to look for. For this simple example, we will only ever need one
HitCountobject and will just assign the primary key
1for it and also search for this one here.
There are two situations that can happen: If the game has been started before, the realm will return a
hitCountobject and we can use that to load the initial state of the
hitCounter(3) using the
hitCount.Value. The other possibility is that the game has not been started before and we need to create the
HitCountobject (4). To create a new object in Realm, you first create it the same way you would create any other object in C# (5). Then we need to add this object to the database. Whenever changes are made to the realm, we need to wrap these changes into a write block to make sure we're prevented from conflicting with other changes that might be going on — for example, on a different thread (6).
Whenever the capsule is clicked, the
hitCountergets incremented in
OnMouseDown(). Here we need to add the change to the database, as well:
Start(), we made sure to create a new
hitCountobject that can be used to load and save changes. So all we need to do here is to update the
Valuewith the new
hitCountervalue (7). Note, as before, we need to wrap this change into a
Writeblock to guarantee data safety.
This is all you need to do for your first game using Realm. Easy, isn't it?
Run it and try it out! Then we will look into how to extend this a little bit.
HitCountExtended.csand ``RealmExampleExtended.cs` in the repository for the finished version.)
To make it easy to compare with the other parts of the series, all we will do in this section is add the key modifiers and save the three different versions:
As you will see in a moment, this small change is almost too simple to create a whole section around it, but it will also show you how easy it is to work with Realm as you go along in your project.
First, let's create a new
HitCountExtended.csso that we can keep and look at both strucutres side by side:
Compared to the
HitCount.cs, we've renamed
Unmodified(1) and added
Shift(2) as well as
Control(3). That's all we need to do in the entity that will hold our data. How do we need to adjust the
First, we'll update the outlets to the Unity editor (the
SerializeFields) by replacing
hitCounterwith those three similar to the previous tutorials:
Equally, we add a
KeyCodefield and use the
HitCountExtendedinstead of the
Let's first adjust the loading of the data. Instead of searching for a
HitCount, we now search for a
If it was found, we extract the three values and set it to the corresponding hit counters to visualize them in the Unity Editor:
If no object was created yet, we will go ahead and create a new one like we did in the simple example:
If you have worked through the previous tutorials, you've seen the
Update()function already. It will be same for this tutorial as well since all it does it detect whichever key modifier is clicked, independent of the way we later on save that modifier:
The important bits here are the check for
LeftControlwhich exist in the enum
KeyCode(1+2). To check if one of those keys is pressed in the current frame (remember,
Update()is called once per frame), we use
Input.GetKey()(1+2) and pass in the key we're interested in. If none of those two keys is pressed, we use the
Unmodifiedversion, which is just
defaultin this case (3).
The final part that has to be adjusted is the mouse click that increments the counter. Depending on the
modifierthat was clicked, we increase the corresponding
After we've done this, we once again update the realm like we did in the simple example, this time updating all three fields in the
With this, the modifiers are done for the Realm example and you can start the game and try it out.
Persisting data in games leads you to many different options to choose from. In this tutorial, we've looked at Realm. It's an easy-to-use and -learn database that can be integrated into your game without much work. All we had to do was add it via NPM, define the objects we use in the game as
RealmObject, and then use
Realm.Write()to add and change data, along with
Realm.Find<>()to retrieve data from the database.
There is a lot more that Realm can do that would go beyond the limits of what can be shown in a single tutorial.
I hope this series gave you some ideas and insights on how to save and load data in Unity games and prepares you for the choice of which one to pick.