SAVE & LOAD SYSTEM in Unity

preview_player
Показать описание
Here's everything you need to know about saving game data in Unity!
privacy TODAY and find out how you can get 3 months free.

····················································································

········································­­·······································­·­····

► All content by Brackeys is 100% free. We believe that education should be available for everyone.

········································­­·······································­·­····

♪ "ES_Dress Code_Black - oomiee" by Epidemic Sound
Рекомендации по теме
Комментарии
Автор

Brackeys: "And now, we are ready to try it out"

Me with 5 errors: *"yes"*

thepokednoob
Автор

"So you've made a game and it played nicely.."


Me: umm

lilmonster
Автор

I feel a little sad watching the videos now knowing they stopped

shahryar
Автор

5 years in and still this is one of the best save and load system tutorial that I found out there.

bonestudios
Автор

Oooo great one! I think this is one of the features *all* games need, but almost *no one* knows how to do it lol. Well done man! ⭐

sykoo
Автор

Quick code review ;-)

* Use using statements for classes that implement IDisposable (e.g. FileStream, BinaryFormatter etc.). Like previous commenters said.
* Use System.IO.Path.Combine to combine paths safely. Paths are constructed differently on different OS. This avoids a lot of potential problems.
* Use a helper method to convert from Vector3 to float array or better yet, make own struct that contains 3 variables and convert between these.

Zicore
Автор

You are the godfather of programming for me. Thank you so much for everything you do.

Unknown-bmui
Автор

One important thing that is missing in this tutorial is to actually separate the data (PlayerData in this instance) from its FileStream cached data.

In this video, it would be a function like:
public PlayerData CopyPlayerData(PlayerData From){
PlayerData To = new PlayerData();
To.level = From.level;
To.health = From.health;
To.position = new float[3];
To.position = From.position[0];
To.position = From.position[1];
To.position = From.position[2];
return To;
}

The reason for doing this is to separate the data sent to the game-usable data from the Filestream data.
Remember that you cannot generate an hard copy a Serializable class (PlayerData in this case) using = .
An hard copy of a Serializable class is a copy cached as its own. It can only be done by using "new".

So, when you do something like SerializableClass A = SerializableClass B, you're basically add a link reference from A to B. A becomes dependent of B meaning that if B cease to exist, A becomes Null and if B becomes Read-Only, A cannot be edited anymore.
This is unlike something like float A = float B which makes A equal to B.

Unity, and pretty much any game engine, are NOT able to generate an hard copy a Serializable Class because it ignores what's to copy.

The only way to generate an hard copy (cached) of a Serializable class is to cast it as a new one. As such, SerializableClass A = new SerializableClass(); makes sure that A is an instance of a Serializable class of its own. When doing so, the class is obviously in its Default state, hence it's at that point that you want to copy its individual values (and by copying, I mean making its values equals and not just some soft copies).

creationsmaxo
Автор

Please, for the love of god, when you are working with a FileStream, please use a try-finally block and call "close()" in the finally clause. Otherwise, if your deserialize() fails, the file will remain open, which can lead to some super-weird and hard to debug effects.

AlanDarkworld
Автор

Thanks for not just going:
"Hey guys, this thing from the app store will do it all for ya.. Bai o/ "
This tutorial was actually helpfull!

DukaSoft
Автор

I really wish that every unity tutorial was by you, like you explain so well and it's so fun learning by you.

xXrandomryzeXx
Автор

Quick tip: Look up how to use the using() statement in C# when working with unmanaged resources such as files. The good news with using the "using" statement is that the file stream will be guaranteed to be closed if you forget to do so yourself.

scriptbrix
Автор

You’re amazing. As an artist I find your tutorials easy to follow. Thank you and your team of people. YouTubes best Unity programming specialist. I’m inspired please continue this channel.

speedyzolt
Автор

It was simple enough, but also in-depth as well! Thanks!

CouchFerretmakesGames
Автор

Love it had to watch 3 different tutorials, Everyone else missed some steps, or didn't fully explain everything and i couldn't get it working. Watched this and now i can save my Gold x, Potions x a, and Apples as well as the position. Works great. Now i need to fully understand, Don't destroy on load. Thanks a lot!!

Zukomazi
Автор

In your save chain you have the SaveSystem handling the data, it's simply passed the player. In the load chain you pass the data itself back to the Player class and let that class handle the data object. You need to pick a convention.

Either pass the player to the SaveSystem.LoadPlayer function as well and have that class manage the data, or pass the already formatted PlayerData object to the SaveSystem.SavePlayer function instead of the player.

xipheonj
Автор

12:10 If you have it set to automatically load data, this will log an error the first time the game is played.
You could of course have a load option and disable that if the save file is not found.

CoolJoshk
Автор

Man, your tutorials are really awesome!
- You know exactly what you're doing
- Your tutorials are pretty clear as a newbie/pro
- It's not too long to watch
- I'm actually learning something
It's so rare nowadays to find YouTubers like you, who are able to teach us effectively things in Unity.
Love the work you've done <3

ramizian
Автор

It's a bit more manual, and you have to update the methods every time you add data that needs to be saved/loaded, but another method I like to use is a BinaryWriter:

using UnityEngine;
using System;
using System.IO;

public static class ClassThatSavesThings
{
public const string PLAYER_SAVE_PATH = @"C:\The\Path\To\The.file"; // The '@' automatically escapes backslashes.

public static void SavePlayer(Player player)
{
// Using a "using" statement causes the stream to be closed automatically when exiting the using.
This is important because nothing is really written to disk until the stream is closed.
using (BinaryWriter writer = new
{
writer.Write(player.level);
writer.Write(player.health);



}
}

public static void LoadPlayer(ref Player player)
{
using (BinaryReader reader = new
{
player.level = reader.ReadInt32();
player.health = reader.ReadInt32();
player.transform = new Vector3(
reader.ReadSingle(),
// "Single" is just another name for "float" in this case. It's technically the other way around, but whatever.
reader.ReadSingle(),
reader.ReadSingle());
}
}
}

Of course, this is a quick and slightly dirty way to do it, but it gives you tons of control over exactly how the data is formatted in binary. The main thing to watch out for is ensuring you read/write data in the same order, otherwise you'll get wrong values for sure. You can also use a BinaryWriter to write to a MemoryStream instead of a FileStream. This is great when you want to get the binary as an array of bytes (byte[]) which can be used to convert your data into Base64.

I wrote this in a plain text editor, so there may be some invalid syntax.

Zethneralith
Автор

Why does learning stuff like this make me all giddy and excited?

cardsatanywhere