Chapter 11: Storing Data and Audio Mixer

In this chapter, we will be looking at common ways of storing and sending data for our game. This will also involve us making use of Unity's ready-made Audio Mixer for us to store the player's volume settings for the game.

As you may recall, in the previous chapter, we had begun making our own pause screen from scratch. We will be carrying on with this in this chapter. We still need to work on the music and sound effects slider on the pause screen. We will hold all Audio Source controls for each sound to be played in the Audio Mixer. The Audio Mixer will act as a central point for all sound and can also be manipulated via scripting, which we will also be doing in this chapter. If our game had more sound effects and more music, an Audio Mixer controlling the game's sound from one place would help us avoid getting tangled up with all the different audio source components attached to game objects.

We will be making use of storing the volume settings with Unity's own PlayerPrefs, which stores data locally on the platform playing the game. This is also known as persistent data because we can turn off the machine that holds the volume information and when the machine is turned back on, the data remains on the system. We will introduce serializing our objects into data and deserializing the data back into objects. This is useful if we want to send batches of data onto a database.

In this chapter, we will be covering the following topics:

  • Using the Audio Mixer
  • Storing data

Let's get started!

Core exam skills covered in this chapter

The following are the core exam skills that will be covered in this chapter:

Programming core interactions:

  • Implement and configure game object behavior and physics.

Developing application systems:

  • Interpret scripts for application interface flow such as menu systems, UI navigation, and application settings.
  • Analyze scripts for user progression features such as scoring, leveling, and in-game economies utilizing technologies such as Unity Analytics and PlayerPrefs.
  • Identify scripts for saving and retrieving application and user data.

Programming for scene and environment design:

  • Determine scripts for implementing audio assets.

Working in professional software development teams:

  • Recognize techniques for structuring scripts for modularity, readability, and reusability.

Technical requirements

The project content for this chapter can be found at https://github.com/PacktPublishing/Unity-Certified-Programmer-Exam-Guide-Second-Edition/tree/main/Chapter_11.

You can download the entirety of each chapter's project files at https://github.com/PacktPublishing/Unity-Certified-Programmer-Exam-Guide-Second-Edition.

All content for this chapter is held in the chapter's unitypackage file, including a Complete folder that contains all of the work that we'll carry out in this chapter.

Check out the following video to see the Code in Action: https://bit.ly/3EYHpxf.

Using the Audio Mixer

As the game grows, it's useful to have a mixer channel that focuses on all the allocated volume levels and sound effects. Otherwise, if not for a separate mixer channel, we would be clicking on various game objects and adjusting each of their components in the Inspector window.

For our game, we are going to keep this simple and create three Audio Groups with no added effects. Let's take a look at what each Audio Group will focus on:

  1. Master Audio Group: Controls the master for the entire game
  2. Music Audio Group: Controls the music of each level
  3. Effects Audio Group: Controls the sound effects of the bullets firing from our player's ship

The following screenshot shows Audio Mixer and the setup for the three Audio Groups:

Figure 11.1 – Audio Mixer window with Master, Music, and Effects Audio Groups

Figure 11.1 – Audio Mixer window with Master, Music, and Effects Audio Groups

Further Information

If you would like to know more about the layout of Audio Mixer, check out the documentation at https://docs.unity3d.com/Manual/AudioMixerOverview.html.

Let's now start by creating the Audio Mixer within the Unity Editor, by following these steps:

  1. In the Project window, go to Assets and right-click on an open space within the folder.
  2. From the drop-down menu, select Create, followed by Audio Mixer. The following screenshot shows the selection being made:
Figure 11.2 – Create an Audio Mixer

Figure 11.2 – Create an Audio Mixer

  1. With that, a new AudioMixer has been created. We are also given the opportunity to rename this file, so let's rename it MasterMixer.

Before we hook up the mixer to the LevelMusic and Player_Bullet game objects (because these are the two game objects making the sounds), we need to go into the Audio Mixer and create Music and Effects mixers first (we only have the master Audio Group on its own at the moment).

Let's have a closer look at our Audio Mixer. To view the Audio Mixer with our MasterMixer, double-click the MasterMixer file in the Project window. We will be presented with the following screen:

Figure 11.3 – Audio Mixer window with Master Audio Group

Figure 11.3 – Audio Mixer window with Master Audio Group

The previous screenshot shows our setup for the Audio Mixer. It consists of four categories:

  1. Mixers (top left): In this category, we only have one Audio Group and that's MasterMixer.
  2. Snapshots: Consider this a save state for our mixer. We can have multiple snapshots, such as a physical Hi-Fi where we can select different saved presets (Rock, Disco, Classical, and so on). Snapshots are used in the same way as presets; it saves us time so that we don't always have to adjust the mixer settings.
  3. Group: Within our MasterMixer will be our two groups – one for Music and the other for Effects. We will create these soon.
  4. Views: Used to save different Audio Mixer UI layouts.

Don't worry too much about the details as we are going to focus mainly on groups. There is more we can do with Audio Mixers. Check the official Unity documentation to find out more at https://docs.unity3d.com/Documentation/Manual/AudioMixer.html.

To add two extra volume mixers next to our Master, we need to do the following:

  1. Right-click Master under the Groups section and select Add child group. We will gain a new mixer, as shown in the following screenshot:
Figure 11.4 – Creating a new Audio Group

Figure 11.4 – Creating a new Audio Group

  1. Right-click New Group (circled in the previous screenshot) and select Rename from the drop-down menu.
  2. Rename New Group to Music.
  3. Repeat steps 1-3 to create another Audio Group and rename it Effects.

The following screenshot shows what the Audio Mixer window will look like now, with all three ASVs:

Figure 11.5 – Audio Mixer with all three Audio Groups

Figure 11.5 – Audio Mixer with all three Audio Groups

Great! Now, we can move on to hooking these audio groups to the game objects we want to affect. The first one is our LevelMusic game object, which is a child of the GameManager game object.

To update our LevelMusic game object's Audio Source component, do the following:

  1. Load up the bootUp scene from the Unity Editor.
  2. In the Hierarchy window, expand the GameManager game object and select the LevelMusic game object.
  3. Back in the Project window, click the arrow to the left of MasterMixer to expand its content.
  4. Click the Music child group and drag it into the Output field of LevelMusic's Audio Source, as shown in the following screenshot:
Figure 11.6 – Drag the Music Audio Group to the LevelMusic Audio Source Output field

Figure 11.6 – Drag the Music Audio Group to the LevelMusic Audio Source Output field

  1. Click Overrides |Apply All in the Inspector window to update the GameManager's prefab settings.

Now, we need to do something similar for our player_bullet prefab. To update its Audio Source with the Effects mixer, do the following:

  1. In the Project window, go to the Assets/Prefab/Player folder. There, you should find our player_bullet game object.
  2. Select player_bullet (denoted as 1 in the following screenshot) and drag and drop the Effects group from MasterMixer (denoted as 2) into player_bullet for Audio Source Output (denoted as 3).

The following screenshot shows what the player_bullet game object's Audio Source should look like in the Inspector window:

Figure 11.7 – Drag the player_bullet's Audio Group Effects into the Audio Source Output field

Figure 11.7 – Drag the player_bullet's Audio Group Effects into the Audio Source Output field

Now, the Audio Mixer is nearly ready to be connected to our pause screen's Music and Effects sliders. We need to do one more thing before we move on to the next section, and that is to make the audio group's volume accessible so we can make it communicate with the pause screen's audio sliders. To do this, we need to set our Audio Mixer's Attenuation Volume property to open or expose it to our scripts.

To expose and name our audio groups, we need to do the following:

  1. In the Project window, go to MasterMixer and expand its content so that we can see its groups.
  2. Select the Music group.
  3. In the Inspector window, we are presented with the Music Group's properties. We want to expose Volume so that we can alter it with our script.
  4. Right-click Volume (In the Inspector window, under Attenuation) and select Expose 'Volume (of Music)' to script, as shown in the following screenshot:
Figure 11.8 – In the Inspector window, right-click Attenuation Volume and select Expose 'Volume (of Music) to script'

Figure 11.8 – In the Inspector window, right-click Attenuation Volume and select Expose 'Volume (of Music) to script'

Now, we also have the option to give the exposed volume a reference name instead of its default name of MyExposedParam.

To change the reference of the exposed Music Volume, do the following:

  1. Back in the Project window, double-click the MasterMixer file.
  2. As you may have noticed, in the top-right corner of Audio Mixer, we are notified that we have Exposed Parameters (1) (denoted by 1 in the following screenshot). The 1 is the Music Volume that we just exposed.
  3. Click Exposed Parameters (1) (denoted by 1).
  4. Right-click the MyExposedParam Volume (of Music) (denoted by 2).
  5. Select Rename from the drop-down menu (denoted by 3).
  6. In the parameter that appears, rename it musicVol (denoted by 4).

The following screenshot shows the stages we just spoke about in the preceding steps:

Figure 11.9 – Renaming MyExposedParam to musicVol

Figure 11.9 – Renaming MyExposedParam to musicVol

I hope you understood this process well, because I want you to do it again but with the Effects group. Also, when it comes to naming the Effects reference in the last step that we just discussed, rename it effectsVol.

Finally, we will have our exposed volume references named like so in our Audio Mixer:

Figure 11.10 – Both of the exposed parameters are renamed

Figure 11.10 – Both of the exposed parameters are renamed

Nice work! Before we move on to the next section, let's briefly recap what we have covered so far in this section:

  • We introduced the Audio Mixer and its benefits.
  • We created Audio Groups for our Mixer.
  • We attached the Audio Mixer to our game object's Audio Source.
  • We exposed the Audio Mixer to our scripts.

In the next section, we are going to code our pause screen's Volume and Effects sliders.

Attaching the Audio Mixer to UI sliders

In this section, we are going to write two methods (SetMusicLevelFromSlider and SetEffectsLevelFromSlider) that attach our pause screen's Music and Effects sliders to the Audio Mixer that we created in the previous section.

Let's start by adding the Music slider to our Audio Mixer via the script, as follows:

  1. In the Project window, go to the PauseComponent script, which should be located in Assets/Script, and open it.

Because we are going to access the Audio Mixer, we need an extra Unity library to let this happen.

  1. At the top of our PauseComponent script, add the following line of code:

    using UnityEngine.Audio;

  2. Now, add a field that will store a reference for our Audio Mixer:

    [SerializeField]

    AudioMixer masterMixer;

  3. We also need to add two more variables for the Music and Effects sliders. Add these below the masterMixer variable, as follows:

    [SerializeField]

    GameObject musicSlider;

    [SerializeField]

    GameObject effectsSlider;

  4. Save the script and return to the Unity Editor.
  5. Load up the level1 scene where we started creating our pause screen.
  6. Select the PauseContainer game object from the Hierarchy window.
  7. In the Inspector window, we will now have three empty parameters in PauseComponent. Here, we can drag the two sliders from the Hierarchy window and our MasterMixer from the Project window, as shown in the following screenshot:
Figure 11.11 – Dragging each game object and file into their directed fields 

Figure 11.11 – Dragging each game object and file into their directed fields 

Now that our three references (music slider, effects slider, and master mixer) are hooked up to their parameters, we can return to our PauseComponent script and code in a method for each of the pause screen's volume sliders.

To add functionality so that our Music slider controls the Music mixer, do the following:

  1. In the PauseComponent script, add a public method within the PauseComponent class:

      public void SetMusicLevelFromSlider()

      {

        masterMixer.SetFloat("musicVol",musicSlider.GetComponent<Slider>

          ().value);

      }

The public method we have just entered, SetMusicLevelFromSlider, will work as an event from the Music slider. Inside the method, we have a reference to our masterMixer. Within this variable, we call its SetFloat function, which takes two parameters. The first is the reference name of the mixer (we called this musicVol earlier in this chapter), while the second is what value it is receiving to be changed. We are sending the value from our pause screen's Music slider.

  1. Save the script and return to the Unity Editor.

Next, we need to attach our Music slider's event to the SetMusicLevelFromSlider method. To make the Music slider communicate with the method, follow these steps:

  1. Still in our level1 scene, in the Hierarchy window, select the Music game object.
  2. In the Inspector window, click the + button at the bottom of the Inspector window to allow an event to be attached to the Slider component (denoted by 1 in the following screenshot).
  3. Drag the PauseContainer game object from the Hierarchy window to the None (Object) parameter (denoted by 2).
  4. Click the No Function drop-down menu and select the method we just coded in SetMusicLevelFromSlider (denoted by 3).

The following screenshot references the previous instructions for the Music game object in the Inspector window:

Figure 11.12 – Three steps in updating the Music game object's music slider event

Figure 11.12 – Three steps in updating the Music game object's music slider event

If we go back to the bootUp scene and click Play in the Unity Editor and then, in the Game window, click the game's pause button when it appears, we will be able to turn the music up and down with the Music slider.

Now, we need to repeat this in a similar fashion for our Effects slider volume to work:

  1. Return to the PauseComponent script and enter the following method:

        public void SetEffectsLevelFromSlider()

      {

        masterMixer.SetFloat("effectsVol",effectsSlider.    GetComponent

           <Slider>().value);

      }

As we can see, the code is virtually the same as the code for SetMusicLevelFromSlider, apart from the variable names.

  1. Save the script.
  2. Return to the Unity Editor and repeat the same procedure for dragging the PauseComponent game object but this time with the Effects game object and selecting SetEffectsLevelFromSlider, as shown in the following screenshot:
Figure 11.13 – Updating the Effects game object audio slider

Figure 11.13 – Updating the Effects game object audio slider

Finally, test to see if the Effects slider works when we run the game.

This will obviously only work in level1 as level2 and level3 don't have the extra game objects. In the next chapter, we will be making a new level3, so if you can hold on until then, it'll save going through the process of removing and adding scenes again.

In this section, we covered the following functionality for the PauseComponent script:

  • Ensuring it recognizes Audio Mixer
  • Ensuring that the Music and Effects UI sliders alter Audio Groups

In the next section, we are going to start looking at how to store our data. We will use the pause screen one more time to show the benefit of our game remembering our volume settings.

Storing data

In this section, we are going to cover how we are going to store our data, such as the game's volume settings so that when we play our game, we don't have to keep setting the volume settings to where they were before. We want the game to remember them for us.

There are multiple ways we can store data. The ones we are going to cover are the two most common choices for Unity development. They are as follows:

  1. PlayerPrefs: This is short for Player Preferences. We can use this to store strings, floats, and integers on the device we are playing our game on. We will be using PlayerPrefs shortly to save our volume settings so that when we turn our game off and back on, it will remember our settings. PlayerPrefs is easily accessible from outside the game with a text file reader. When it comes to development, make sure you don't use PlayerPrefs to store sensitive information such as credit card details or things that would give a player an unfair advantage such as storing lives, energy, score, in-game credit, and so on. For more information about PlayerPrefs, check Unity's description at https://docs.unity3d.com/Documentation/ScriptReference/PlayerPrefs.html.
  2. JSON: This is short for JavaScript Object Notation and is typically used when sending and receiving data from our device to another application or even from a server online somewhere in the cloud. One of the benefits of JSON over PlayerPrefs is that it uses data types such as int, float, and string, just like PlayerPrefs, but also object (our classes act as blueprints so that we can make objects), array, bool, and null.

It's wise to use this form of application programming interface (API) for transferring game data (lives, levels, player progress, energy, and so on), but don't store highly personal details locally with regards to in-game credit, bank details, personal addresses, and emails, unless you are using some form of encryption.

Information

An API basically tells us how applications communicate with each other.

For more information about JSON with Unity, check the documentation at https://docs.unity3d.com/Documentation/Manual/JSONSerialization.html.

In the following sections, we are going to cover these two ways of storing data on the basis they are officially covered by Unity and are likely to be mentioned in your exam:

  • PlayerPrefs and volume settings
  • JSON and storing game stats
  • Adding JSON variables

Let's make a start by looking at how to use PlayerPrefs and revisit our pause screen one last time.

PlayerPrefs and volume settings

As we know, our game has volume controls for its music and sound effects on the pause screen. To make our game remember these volume settings, even when the game has been turned off and back on again, we need to do the following:

  1. In the Project window of the Unity Editor, go to Assets/Script.
  2. Double-click the PauseComponent script.
  3. Scroll down to the SetMusicLevelFromSlider method and add the following extra line of code at the bottom but within the method's scope. The following code shows what the method now looks like with the added code:

      public void SetMusicLevelFromSlider()

      {

        masterMixer.SetFloat("musicVol",musicSlider.        GetComponent

           <Slider>().value);

        PlayerPrefs.SetFloat("musicVolume",musicSlider.        GetComponent

           <Slider>().value);    // << NEW CODE LINE

      }

In the preceding code, we used the value from our music <Slider> component and applied its float value to the PlayerPrefs float with musicVolume as our key (the reference name to identify the PlayerPrefs value).

  1. Do the same for the effects method:

        public void SetEffectsLevelFromSlider()

      {

        masterMixer.SetFloat("effectsVol",effectsSlider.        GetComponent

          <Slider>().value);

        PlayerPrefs.SetFloat("effectsVolume",effectsSlider.        GetComponent

          <Slider>().value);  // << NEW CODE LINE

      }

That's our PlayerPrefs file ready to store the music and effects volume. The next thing to do is reapply the music/effects volume the next time we load the level from our PlayerPrefs.

To grab the music volume setting from our PlayerPrefs, do the following:

  1. Reopen the PauseComponent script.
  2. Within the PauseComponent class, enter the following code at the bottom of the Awake function:

        masterMixer.SetFloat("musicVol",PlayerPrefs.GetFloat("musicVolume"));

        masterMixer.SetFloat("effectsVol",PlayerPrefs.GetFloat("effectsVolume"));

In the preceding code, we are reapplying our saved PlayerPrefs values for our music and effects volume (which are both floats) to our Audio Mixer's Audio Groups.

The volumes that we want the mixers to have are now set. The last thing we need to do is to set both volume sliders to their UI positions.

  1. To update the Music and Effects sliders visually, we need to add the following code within our PauseComponent:

      float GetMusicLevelFromMixer()

      {

        float musicMixersValue;

        bool result = masterMixer.GetFloat("musicVol",

           out musicMixersValue);

        

        if (result)

        {

          return musicMixersValue;

        }

        else

        {

          return 0;

        }

      }

The preceding code is a method that returns a float value called GetMusicLevelFromMixer.

Let's go through the steps of this GetMusicLevelFromMixer:

  1. In this method, we create a float variable called musicMixersValue.
  2. The line after musicMixersValue checks to see whether the masterMixer instance contains an Audio Group called musicVol. We know it does because we set it earlier when we exposed each of the volume settings from the Audio Mixer, as shown in the following screenshot:

Figure 11.14 – Our named exposed parameters

Figure 11.14 – Our named exposed parameters

  1. So, if masterMixer does contain a float value with the name (key) of musicVol, we will store it in a float named musicMixersValue.
  2. masterMixer.GetFloat will send a true or false value if masterMixer does or does not contain a float that is also stored in a bool value, respectively.
  3. If the bool value is true, the float value from masterMixer is returned from the method; otherwise, it will return 0.

Next, we need to call this GetMusicLevelFromMixer and make it so it sends its value to the music slider. Let's code this in now.

  1. Within the PauseComponent script, at the top, in the Awake function, add the following code below the two masterMixer coded lines:

    musicSlider.GetComponent<Slider>().value = GetMusicLevelFromMixer();

In the preceding piece of code, we are sending the result from our GetMusicLevelFromMixer to the value of our musicSlider when the level starts.

That's our music slider set. Now, we need to repeat this process for our effects slider. The process is the same, apart from using the effect slider's variables, so without repeating the same process, I want you to do the following:

  1. Create a GetEffectsLevelFromMixer method using the same code pattern as GetMusicLevelFromMixer but using effectsVol instead of musicVol.
  2. Assign the results of GetEffectsLevelFromMixer to the effectsSlider variable in the Awake function. Use the musicSlider variable for reference.

Give it a go – if you're struggling, check out the Complete folder in this book's GitHub repository.

Save the script and return to the Unity Editor. Play the first level, change the volume, quit the game, and return to the first level to see if our volume has been saved for the music and effects sliders.

Now, we will move on and learn how to store and send data in a slightly different way.

JSON and storing game stats

JSON is great for creating, storing, and updating information across our game. As we mentioned earlier in this chapter, JSON is typically used for sending data from our game to a server online where the JSON data can be delivered to another set of data.

The best way JSON was explained to me is with an analogy of me being at a restaurant, sitting at a table (my game); the waiter comes over and takes my (JSON) order, then sends it to the kitchen (the online server). Finally, the waiter returns with my food.

With regards to coding JSON, we are storing variables in a single class, then serializing the class (object) into data (system memory or file). From there, we can transfer this data to an actual file or upload it to a server on a database. This whole process can also be reversed, where we take the data and return it as an object. This is called deserializing.

Now, let's move on to coding some JSON values.

Adding JSON variables

The objective of working with JSON is to create a simple way of storing and updating data with JSON. In our project, we will provide a simple example of storing statistical data for our game. When the player completes the game, we will store data and put it in JSON format.

The three variables we are going to store are as follows:

  • livesLeft: How many lives the player has left
  • completed: When the player has completed the game
  • score: Stores the player's score

Let's make a start by creating a new script that will receive our game's three statistical updates. These will then be converted into JSON format. Follow these steps:

  1. Create a new script (if you don't know how to do that, revisit the Updating our camera properties via script section in Chapter 2, Adding and Manipulating Objects).
  2. Call the new script GameStats.
  3. Before we open the GameStats script, I recommend that you keep your files stored in the Assets/Script folder location.
  4. Next, we can open the GameStats script and code in the following variables:

    public class GameStats

    {

        public int livesLeft;

        public string completed;

        public int score;

    }

Notice how the GameStats script doesn't require a library or need to inherit MonoBehaviour. We don't require either of these extra functionalities.

When the player completes the game, we will take these three readings and store them in JSON format. From there, we can convert this data into a JSON file. This process is known as serialization.

Serialization/Deserialization

These two terms basically refer to the direction that data is stored in.

Serialization: This refers to converting an object from our script and turning it into bytes (a file, in our case).

Deserialization: As you can probably imagine, deserialization is the opposite of serialization. This means we are taking our raw data (file) and converting it into objects.

  1. Save the script.

Next, we need to write some code that will update the player's lives, time and date, and score. We are going to do this when we play through the game and complete level 3. In this case, we need to go to our ScenesManager and update the code.

To update our ScenesManager so that it takes a reading of our player's stats and converts them into JSON format, we need to do the following:

  1. In the Unity Editor, go to where our ScenesManager script is. This should be in the Assets/Script folder.
  2. Double-click the file to open it in our IDE and scroll down to the point where we check to see if the game has ended. This is located in the GameTimer method.

The following screenshot shows where in the ScenesManager script we need to add our new method:

Figure 11.15 – Placement marked where to add new code in our ScenesManager script

Figure 11.15 – Placement marked where to add new code in our ScenesManager script

In the preceding screenshot, there is an asterisk (*) marking where we are going to enter the name of our new method, along with a string parameter, which will be the name of the level we have completed.

  1. Enter the following method name where the * is in the previous screenshot:

    SendInJsonFormat(SceneManager.GetActiveScene().name);

  2. Next, we need to create the SendInJsonFormat method. Scroll down to a point in the ScenesManager script where we are still inside its class but not another method and enter the following:

      void SendInJsonFormat(string lastLevel)

      {

        if (lastLevel == "level3")

          {

            GameStats gameStats = new GameStats();

            gameStats.livesLeft = GameManager.playerLives;

            gameStats.completed = System.DateTime.Now.ToString();

             gameStats.score = GetComponent<ScoreManager>().             PlayersScore;

            

            string json = JsonUtility.ToJson(gameStats,true);

            Debug.Log(json);

          }

      }

In the previous code, we go through this series of steps:

  1. We have our SendInJsonFormat method, which takes a string parameter.
  2. Inside the SendInJsonFormat method, we set an if statement that checks if the lastLevel string contains the level3 value.
  3. If lastLevel is equal to the level3 string, we go through the following steps inside the if statement:
  4. We create an instance of the GameStats class we made earlier in this chapter.
  5. We access its livesLeft public variable and apply the static playerLives variable from the GameManager class.
  6. The next variable shows the date and time we completed the game. We send the command from the System library, which gives us the date and time, and we cast this as a string (ToString()). We send this result to the gameStats instance into the completed variable.
  7. The last variable we send data is the player's score. We get this from the playerScore static variable from our ScoreManager class.

Now that we have applied the three variables to our gameStats instance, we can use Unity's JsonUtility class to send our gameStats into the ToJson function.

We can also make the JSON data readable by adding true to the parameter so that when we send a log command to the console to see that this has worked correctly, we can read the results.

  1. Save the script and jump back into the Unity Editor and complete the game from the bootUp scene to the gameOver scene.

The following screenshot shows the console log when I played through the game and completed level 3:

Figure 11.16 – Console window giving stats about our game

Figure 11.16 – Console window giving stats about our game

As you can see, we have the data from our script but displayed in JSON format.

This information can be saved to a physical file or can be sent to a server to keep a record of our player's gameplay and/or deserialize the results later on with our project (check out the following tip if you are interested in this). The point is that we are storing and carrying data that can be sent away for us or another system to pick up, store, and alter.

Further Information

At this point, we have successfully taken the variables from our object and converted them into JSON data format (serialization).

Now, imagine if we altered our data (changed its values) and wanted to bring that data back into our game's code and into a class. The reverse method would be GameStats loadJsonData = JsonUtility.FromJson<GameStats>(json);.

This would update our GameStats variables from the JSON file. You can imagine that this would be handy for saving and loading data in games.

Next, we will take the most current JSON data file and send it to the device (the machine we play the game on). To make and store a JSON file containing our custom-made stats, do the following:

  1. Return to the ScenesManager script.
  2. Scroll to where we created the SendInJsonFormat method.
  3. Within the method's if statement, at the bottom, inside the scope of the if statement, add the following two lines of code:

    Debug.Log(Application.persistentDataPath + "/GameStatsSaved.json");

    System.IO.File.WriteAllText(Application.persistentDataPath +

       "/GameStatsSaved.json",json);

The preceding code block shows that we don't necessarily need to add Debug.Log and shows us where the next line of code is creating and storing our JSON file. Each platform will store data in different folders. For more information on the locations for different platforms, please refer to Unity's own documentation about persistent data at https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html.

My system is a Windows PC, so Debug.Log will display the following location on my system:

Figure 11.17 – Windows location of JSON file

Figure 11.17 – Windows location of JSON file

The second line of the code we just entered is using a system library and uses a function (Application.persistentDataPath) that will refer to our device's local storage. Then, after the function, we add the name we want to use to refer to our JSON file (/GameStatsSaved.json), along with the format type, which is json.

  1. Save the script.
  2. Return to the Unity Editor, play all the way to the end of the game, and go to the location that is displayed on the console screen. The following screenshot shows the location of the file that our game has made:
Figure 11.18 – Windows location of our JSON file

Figure 11.18 – Windows location of our JSON file

  1. Double-click the file to view its content. As you will see, this is where our game's stats are kept, as shown in the following screenshot:
Figure 11.19 – The content of our JSON file

Figure 11.19 – The content of our JSON file

With this, we are now aware of how to store non-sensitive data such as our game's volume (PlayerPrefs), as well as how to create, store, and send other types of data in JSON format.

Now, let's summarize this chapter.

Further Information

For more information about all of these events, check the official Unity documentation at https://docs.unity3d.com/Manual/UnityAnalyticsEvents.html.

Summary

This chapter covered a variety of topics, including understanding Unity's Audio Mixer, which is where we can control the sounds in our game, and altering levels with our script. Then, we moved on and looked at storing data with PlayerPrefs and custom storage in JSON format in order to recognize the differences between the two ways of storing data. For JSON, we converted our data from object-based data into bytes and stored the results in a file (serialization).

In future projects, you will likely make use of the coding we covered in the last two chapters regarding storing and reapplying data such as music and sound effect volume sliders. Hopefully, you will also be able to go further with this data by using other components in your projects so that your game can send out data onto the cloud and monitor your players' progress as helpful feedback to improve development.

In the next chapter, we are going to look at pathfinding and how to improve the overall performance of our game.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset