Daily progress: Saving and Loading Data in Unity
With our Overview panel all filled out, it means we also have our case data all filled out as well. We’ll eventually want to save it to Amazon to retrieve at any time later, but in order to do that, we’ll need to save that information into a file.
Some common forms of saving in unity are JSON or JavaScript Object Notation, which takes code and converts it to formatted string data that looks like javascript data. and there’s also Unitys PlayerPrefs but it’s not recommended for sensitive or private info since its widely known for being insecure.
The third and what we’ll be doing for our data will be Serialization methods, which is turning our data into a bunch of bytes and then saving it into a serialized binary file.
Serialization is what turns an object into a stream of bytes, and we can use [System.Serializable] to let Unity know that whatever variables follow, can be converted into bytes for storage:
The conversion process is called serialization and converting things back to actual game variables is called deserialization.
So let’s prepare to save our data, we’ll do this in our UIManager and create a SubmitButton method for it.
What needs to get done is:
- Create a new case to save
- populate the case data
- open a file stream to turn that new case data into a file.
- and then begin the Amazon AWS process.
So let’s begin!
we have a new case, let’s start filling it out:
If this looks familiar, you are correct! let’s fill the rest of our known case elements!
Next, we’ll begin the process of converting to bytes using something called a binary formatter. We’ll need to use the using System.Runtime.Serialization.Formatters.Binary namespace:
Now that we’ll be actually saving to a file, we’ll also need to use the System.IO namespace:
Now we’ll actually write the data.
FileStream will create the file using the caseID and save it with a .dat extension, and then using bf.Serialize, we’ll save our data into that file, and of course when we’re done, we close the file so it doesn’t accidentally end up corrupted and unreadable.
When we test the app out, everything seems to work ok up until we actually try to save the file, Unity tells us that Images aren’t serializable.
It does make sense if you think about it, things like text and strings are easily converted to binary 1’s and zeroes but things like images and audio aren’t native language objects so need conversion. We’ll be able to do it, but we’ll need to change a few things first. In our Case class, we’ll change our photoTaken object type from a raw image to an array of bytes.
This is going to cause a lot of errors but we’ll take each case as they come.
The first case is in the Overview panel,
and next in the TakePhotoPanel where we’ll have to do some conversions as well.
For the TakePhotoPanel, we’ll take our texture and convert it to a Texture2D and then we’ll be able to convert it to a PNG which we can change to a byte array.
So we create a variable called convertedPhoto of type Texture2D, and we put photoTaken’s texture inside but we tell Unity with a cast of Texture2D to force it as that kind of data into the new variable.
Next, we use a built in function to encode the image to a PNG and get stored as bytes in imgData which then finally gets put into the activeCase.
Finally, we’ll take care of the remaining errors in the Overview panels by reconstructing the image from the serialized version there.
Thankfully there’s a helper object called ImageConversion that we can use to reconstruct the image.
Apparently, while this code works OK in the emulator, it will crash on an actual device. It needed the actual path to the image location where it was saved, so a few more tweaks to the code are in order:
In the TakePhoto panel code,
We’re taking the photo but don’t have access to its location. To discover it, we’ll create a string variable called imgPath;
We’ll assign the cameras path variable to it when we take the photo.
Also note that the NativeCamera.LoadImageAtPath(path, maxSize) now has an extra boolean, false. This will allow us to modify the image later.
Now we’ll have to create a 2d Texture, apply it from the image path, encode it into a png and then store the bytes to activeCase.photoTaken.
This should fix everything and the case file should be successfully saving now.
For testing purposes, we will want the option to not take a photo so we’ll account for that:
So we basically just create the byte array and make it null. So if it’s filled up or not won’t matter, the program will still run and not crash.
We still need to know where Application.path is so we can see any created files, we’ll add a Debug.Log to the UIManager to let us know.
and here’s my path!
I can find my data at home/stevethedragon/.var/app/com.unity.UnityHub/config/unity3d/SteveTheDragonGames/ServiceAdjustmentApp ! Linux is totally user friendly guys!
Ok, so let’s do some file hunting:
Ok, it wasn’t that hard to find, but I’m still making a link to this folder from my desktop so I won’t have to dive into the file system again…whew! Anyway, there they are in all of their filesystem glory! We have actual case files we can upload to amazon now that contain all of our saved data!