I really needed a video like this 3 years ago, when I started using Unity. I remember I struggled a lot to build a save/load system for my game. After watching the video I'm happy to see I've done a good job. I developed a pretty similar system :)
Great content covering the options and explanations/reasoning to help choose the correct route- Please keep making content like this.. and consider zooming in on the code for easier readability in the video for future tutorials. Thank you!
players prefs is exactly self explanatory though. you use it for your preferences such as volume, sensitivity, keybinds etc. things that don't have any game breaking impact if edited.
I really appreciate the effort and Saving / Serialization is definitely something Unity should put out more tutorials. But this one failed to deliver any knowledge imo. Even as someone with basic knowledge of JSON serialization, this was horrible to follow or understand. Long breaks without speech while silently commenting out code. No explanation of each function, or its lines. FileManager? I've seen much better explanations from random RUclipsrs and would expect a lot more from Unity. Sorry if this is a bit harsh.
I would like to have mention the drawbacks. This does not work on spawned enemies. Everything saved must come with the scene. Also if the scene changes in case of a patch, this solution breaks. Consider a new enemy is in the patch. He will probably get the id of the enemy right after him and so on. All saved data on and after this enemy will be corrupted. And now imagine enemies with different data. Crash. As long as there is no way to produce an unique Id taking more information into account (e.g. spawn position, time, whatever) data cannot be reproduced in case anything changes (scene).
Great video. So then in the scenario where we have a game and we're keeping important player data on a remote server, and we're heeding the advice of not trusting anything the game client says, what's the right way to do user auth such that they're reliably retrieving their own save data?
There are some complaints in this thread about things not being clear, of pieces missing - if you have any questions, just reply and I can answer them. I got this working just fine.
@@beneuser1220 you can then set up a GUID string field in your main enemy class and retrieve the GUID by putting this in your Start: private string _enemyGuid; void Start() { _enemyGuid = GetComponent().GUID; }
@@beneuser1220 You can be call you GUID variable UUID if you want, makes no difference, idea is the same. GUID is generally understood to be Microsoft's implementation of UUID, though there can be subtle differences in GUID standard Vs RFC4122 UUID, but not anything you need to think about. Let me know if you got this working - you'll need to either call the Save and Load methods via Awake, Start or OnDestroy, or via UI buttons, depending on your preference and game style.
@@beneuser1220 Just remember that a prefab will be given the same GUID if you don't unpack it first. If you are instantiating via a prefab, you can assign the GUID at that point through script. I also use a button (Odin.Inspector) in the Inspector for resetting the GUID when I unpack the prefab. If you don't have Odin, you could create your own custom drawer for this - shouldn't be too difficult.
I would appreciate more content on server side saving as in "actual implementation". JSON and PlayerPrefs are both relatively easy to understand while server side saving requires some more thinking ahead. Expecially mobile integration would be interesting, e. g. for offline states of the player. Thanks for that overview, though! Great presentation!
@@bronsonzgeb5651 Thanks for the detailed answer! I guess I'll have to have a look at the server docs more properly then ;) Was thinking about an off the shelf solution for android using the PlayStore built-in options, but maybe that doesn't even exist? At least now I have some starting points, thanks!
@@bronsonzgeb5651 I kinda am, yes. Just some simple systems that are cheat-proof. E. g. running a small game look (Tetris, Snake, etc.) locally but saving the (high-)score directly on the server. The score itself can savely be stored, I'm sure, but is it generated safely enough to prevent cheating? These kind of things currently grind my gears ;) Looking forward to more content of yours on persistent data, then :)
Thank you great video! question? how would you load Json data between scenes? I made a start menu, but as soon as I load my scene from, the menu I created, I receive compiler errors. however if I load the same data staring from the scene I'm trying to load, instead of the menu scene, it works perfectly??? I would appreciate some help upstanding this, but regardless. thank you for a wonderful tutorial
How to save the data after adding new features to my game? Like when users download an update from playstore and then keep users old data. Is the method shown in this video work?
this video is great, but i would like to see a video of someone using these things starting from a blank project and start with variable data, then go up the list. like a name and ID system that saves the stuff would be nice.
As far as I've read, there is no way to produce an unique Id. So you can also just register all enemies in a list in Awake() and save this list. If an enemy was Destroyed, the list entry is null, so you save a 'Destroyed' information for that index. So your uuID saves no purpose. But both solutions cannot handle spawned enemies. All you can save here must come with the scene. Any ideas of how to address this problem?
É basicamente o que eu faço, criei uma biblioteca minha mesmo que salva tudo em uma cadeia de bytes organizados hehehe Consome muito menos espaço em disco porque não tem overhead né.
How am I supposed to give every savable object in my game a UUID that is always the same every time the game is loaded? I can't just assign a UUID in the constructor and I don't want to have to assign it one in the inspector. They need to have a consistent UUID so when I save/load their data it's associated with the correct entity.
You could do [SerializeField] string uuid = System.Guid.NewGuid().ToString(); in class as default value, so every time it'll set new guid, which is not likely to overlap. I did it myself, seems to work
a bit complicated for a noob. I wish you would have used a more clear cut example for the unityJson. It was helpful to get a good understanding of how it works, but im finding it difficult to apply it while learning to code. nicely done, just above my head. intermediate+
Very strong save system, it's a pleasure to follow the different steps but for the Uuid, how did you do to make them persistent. I have been working on it for many days and I don't find a way to do it.
Please tell me the name of your color theme (VS), looks nice to my eyes. By the way, why not store data at the binary level? Using Protobuf.Serialize() ? like a [ProtoBuf.ProtoContract] public struct Data { [ProtoBuf.ProtoMember(1)] public string UUID; [ProtoBuf.ProtoMember(2)] public int M_Data1; [ProtoBuf.ProtoMember(3)] public int M_Data2; } This will improve the performance of the game, you can also put the UUID in the file name.
JSON is a tree structure, SQL is a flat table structure. If your data is more tabular in nature (like how some RPGs have a lot of flat tables for things like XP gains), you might have an easier time using sqlite. If you want objects to take care of themselves, JSON can easily store all their information in the same structure as your C# class, which is very nice. If you instead want a very centralised data model where everything needs to have lightning-fast access to a centralised data store, sqlite is the way to go.
Was this edited to cut out the time Unity is saving/reloadind when hitting play? I'm just wondering if I'm missing a setting that'll save me hours of my life.
so i use json to save data but i made a encryption system to encrypt the keys using some sketchy algorithm imade.. is it safe or is it easily reversable because its json
Amazing tutorial. I also have a save system playlist series. It covers from player-pref to Firebase. I am currently editing the video with NodeJS as the back-end server for saving data. Any feedback on it will be really helpful.
It's a custom class with 2 static methods, WriteToFile and LoadFromFile. He starts his explanation at 17:25 . Here is what it looks like. public class FileManager { public static bool WriteToFile(string a_filename, string a_filecontent) { var fullPath = Path.Combine(Application.persistentDataPath, a_filename); try { File.WriteAllText(fullPath, a_filecontent); return true; } catch (Exception e) { Debug.LogError("Fail to write to " + fullPath + " exception:" + e); } return false; } public static bool LoadFromFile(string a_filename, out string result) { var fullPath = Path.Combine(Application.persistentDataPath, a_filename); try { result = File.ReadAllText(fullPath); return true; } catch (Exception e) { Debug.LogError("Fail to read from " + fullPath + " exception:" + e); result = ""; return false; } } }
To understand this tutorial, you must already know 90% of what he's attempting to explain. Does not write or explain why or how most things work. Shows snippets of code with no references on what makes them work. Hopefully this helps the more advanced pupils.
this is some kind of spaghetti tutorial so many things not explained uncommenting all this code from earlier, no mention of interfaces, gameviewconroller etc, you dont teach people like that, you demonstrate with the most simple example to outline the flow. Then build complexity on top of that. This is a mess.
Player Prefs is really dirty in windows, it will write data in the registry. Just make a Json (or XML) in any case. Why dictionary can't be serialized? For Assets (Item sprites...), the best way to do it is to put them in the "Resources" folder and name them with an ID system. Then check if they exist when loading your data to avoid error. It's very error prone, but it's easy and Unity offers no solution.
@@ayan3789 Normally you don't want to balance ragdolls. Instead you want to set them to kinematic movement and control them directly (with no physics), then "trigger" ragdolling by letting the rigidbody take over
Update. This awful developer no longer works at unity and went on to make the most beginner game I've ever seen. No wonder this engine and company fell through, this guy was making their tools.
Horrific tutorial, find another video. Uncommenting out code surrounded by unrelated functions looks bad. Hearing every small sound and keystroke is bad. What really blows me away is you make a reference to custom code, and explain it AT THE END OF THE SECTION. I don't think there's a nice way to put how inept that is. You breeze right past introducing FileManager to the extent I rewatched this thing from the start a few times to see if you included it, instead it was 17 minutes in. Random comments had to point this out. Please delist this, it should not be a top result from google.
These videos always come up right AFTER I spent days banging my head against an issue 😂 I like to tell myself I learned a lot in the process 😜
Hahaha ikr
I really needed a video like this 3 years ago, when I started using Unity. I remember I struggled a lot to build a save/load system for my game. After watching the video I'm happy to see I've done a good job. I developed a pretty similar system :)
One of the better tutorials I've seen on Unity channel. I think these generalised tutorials make for very strong content.
agreed
I was just finding the best ways to save my app data and then this video comes in. Looking forward to use Json to do so for now.
Great content covering the options and explanations/reasoning to help choose the correct route- Please keep making content like this.. and consider zooming in on the code for easier readability in the video for future tutorials. Thank you!
players prefs is exactly self explanatory though. you use it for your preferences such as volume, sensitivity, keybinds etc. things that don't have any game breaking impact if edited.
great timing! was convinced to buy the easy save and it's nice
Just what I needed! Thanks! And the guy should not be so nervous) Great job!
I really appreciate the effort and Saving / Serialization is definitely something Unity should put out more tutorials. But this one failed to deliver any knowledge imo. Even as someone with basic knowledge of JSON serialization, this was horrible to follow or understand. Long breaks without speech while silently commenting out code. No explanation of each function, or its lines. FileManager? I've seen much better explanations from random RUclipsrs and would expect a lot more from Unity. Sorry if this is a bit harsh.
I would like to have mention the drawbacks. This does not work on spawned enemies. Everything saved must come with the scene.
Also if the scene changes in case of a patch, this solution breaks. Consider a new enemy is in the patch. He will probably get the id of the enemy right after him and so on. All saved data on and after this enemy will be corrupted. And now imagine enemies with different data. Crash.
As long as there is no way to produce an unique Id taking more information into account (e.g. spawn position, time, whatever) data cannot be reproduced in case anything changes (scene).
Really enjoyed your presentation, clarity and explanations. Really pulled all the stuff I've been reading and watching together. 👍🍻
I'm a simple man I saw Vscode and I give a like to the video
Great video. So then in the scenario where we have a game and we're keeping important player data on a remote server, and we're heeding the advice of not trusting anything the game client says, what's the right way to do user auth such that they're reliably retrieving their own save data?
4:40 If your registry is being corrupted, you have much bigger problems that saving to files won't fix.
the problem with jsonutillty that if you updated a value in will update all the other values in the json file
What's inside the FileManager class? He didn't mention it.
@@bronsonzgeb5651 ok, thanks a lot.
Maybe it's just me, but I couldn't really follow the JSON example. I can't see what files/classes you are looking at and how they are connected.
Very nice :) not many vids covering my preferred ways to save
how did you Create the Uuid? i see you use it in many places. did you build it by yourself or with unity build in class?
it's built-in C#. string guid = System.Guid.NewGuid().ToString(); (using System;)
Awesome tutorial, practical and succinct. Thanks!
what is the LoadFromFile ? What data type is it? Cannot access it
Should have had timestamps
@@bronsonzgeb5651 oh, great!
There are some complaints in this thread about things not being clear, of pieces missing - if you have any questions, just reply and I can answer them. I got this working just fine.
I have the problem, that I don't know how to set up the UUID for my enemies. How did you do that?
@@beneuser1220 attach this script to all your enemies:
using UnityEngine;
[ExecuteAlways]
public class GenerateGUID : MonoBehaviour
{
[SerializeField]
private string _gUID = "";
public string GUID { get => _gUID; set => _gUID = value; }
private void OnValidate()
{
// Only populate in the editor
if (!Application.IsPlaying(gameObject))
{
// Ensure the object has a guaranteed unique id
if (_gUID == "")
{
//Assign GUID
_gUID = System.Guid.NewGuid().ToString();
}
}
}
@@beneuser1220 you can then set up a GUID string field in your main enemy class and retrieve the GUID by putting this in your Start:
private string _enemyGuid;
void Start()
{
_enemyGuid = GetComponent().GUID;
}
@@beneuser1220 You can be call you GUID variable UUID if you want, makes no difference, idea is the same. GUID is generally understood to be Microsoft's implementation of UUID, though there can be subtle differences in GUID standard Vs RFC4122 UUID, but not anything you need to think about.
Let me know if you got this working - you'll need to either call the Save and Load methods via Awake, Start or OnDestroy, or via UI buttons, depending on your preference and game style.
@@beneuser1220 Just remember that a prefab will be given the same GUID if you don't unpack it first. If you are instantiating via a prefab, you can assign the GUID at that point through script. I also use a button (Odin.Inspector) in the Inspector for resetting the GUID when I unpack the prefab. If you don't have Odin, you could create your own custom drawer for this - shouldn't be too difficult.
Awesome tutorial on save data! Thank you!
I would appreciate more content on server side saving as in "actual implementation". JSON and PlayerPrefs are both relatively easy to understand while server side saving requires some more thinking ahead. Expecially mobile integration would be interesting, e. g. for offline states of the player.
Thanks for that overview, though! Great presentation!
@@bronsonzgeb5651 Thanks for the detailed answer! I guess I'll have to have a look at the server docs more properly then ;) Was thinking about an off the shelf solution for android using the PlayStore built-in options, but maybe that doesn't even exist? At least now I have some starting points, thanks!
@@bronsonzgeb5651 I kinda am, yes. Just some simple systems that are cheat-proof. E. g. running a small game look (Tetris, Snake, etc.) locally but saving the (high-)score directly on the server. The score itself can savely be stored, I'm sure, but is it generated safely enough to prevent cheating? These kind of things currently grind my gears ;) Looking forward to more content of yours on persistent data, then :)
@@bronsonzgeb5651 Well, that's a great idea. In my special case I can think of some parameters right away ;) Thanks a ton!
Thank you so much for making this video
Error with Path and File does not exist in the current content
How to save animation data so the player can load mid attack animation
thankiu this is what i need
Thank you great video! question? how would you load Json data between scenes? I made a start menu, but as soon as I load my scene from, the menu I created, I receive compiler errors. however if I load the same data staring from the scene I'm trying to load, instead of the menu scene, it works perfectly???
I would appreciate some help upstanding this, but regardless. thank you for a wonderful tutorial
i just want to know how to change the save location... as a player i hate it when games save in appdata.
How to save the data after adding new features to my game? Like when users download an update from playstore and then keep users old data. Is the method shown in this video work?
this video is great, but i would like to see a video of someone using these things starting from a blank project and start with variable data, then go up the list. like a name and ID system that saves the stuff would be nice.
How to save data on server load pls make a video on this or any guidance
what about using scriptable objects for saving game data?
JSON compact? It's an ASCII or Unicode representation of simple types that uses a lot more space
Where is FileManager? where do I import it from?
FileManager of the video is a class that the teacher has coded. He explains how at min 17:27. It is not from the engine namespaces.
@@bronsonzgeb5651 Thank you for requesting the links, for sure it will be helpful! Congratz on the video!
As far as I've read, there is no way to produce an unique Id. So you can also just register all enemies in a list in Awake() and save this list. If an enemy was Destroyed, the list entry is null, so you save a 'Destroyed' information for that index. So your uuID saves no purpose.
But both solutions cannot handle spawned enemies. All you can save here must come with the scene. Any ideas of how to address this problem?
Wouldn't serializing in binary be another good option?
É basicamente o que eu faço, criei uma biblioteca minha mesmo que salva tudo em uma cadeia de bytes organizados hehehe Consome muito menos espaço em disco porque não tem overhead né.
How am I supposed to give every savable object in my game a UUID that is always the same every time the game is loaded? I can't just assign a UUID in the constructor and I don't want to have to assign it one in the inspector. They need to have a consistent UUID so when I save/load their data it's associated with the correct entity.
You could do
[SerializeField] string uuid = System.Guid.NewGuid().ToString(); in class as default value, so every time it'll set new guid, which is not likely to overlap. I did it myself, seems to work
@@saniel2748 I guess. Can I use [HideInInspector] too since I don't want it to be seen by my artists?
@@pt8306 i would recommend making your own attribute because HideInInspector is not visible even in debug view
But technically yes, you can
@@saniel2748 how can I detect debug mode in my editor script?
@@pt8306 I mean switching the inspector to debug view
how do you access/find the savedata.dat file on mac?
Nice content.
a bit complicated for a noob. I wish you would have used a more clear cut example for the unityJson. It was helpful to get a good understanding of how it works, but im finding it difficult to apply it while learning to code. nicely done, just above my head. intermediate+
Very strong save system, it's a pleasure to follow the different steps but for the Uuid, how did you do to make them persistent. I have been working on it for many days and I don't find a way to do it.
Please tell me the name of your color theme (VS), looks nice to my eyes.
By the way, why not store data at the binary level? Using Protobuf.Serialize() ? like a
[ProtoBuf.ProtoContract]
public struct Data
{
[ProtoBuf.ProtoMember(1)]
public string UUID;
[ProtoBuf.ProtoMember(2)]
public int M_Data1;
[ProtoBuf.ProtoMember(3)]
public int M_Data2;
}
This will improve the performance of the game, you can also put the UUID in the file name.
@@bronsonzgeb5651 Thanks!
Is there any advantages to using sqllite? I have lots of data. Mostly structured.
JSON is a tree structure, SQL is a flat table structure. If your data is more tabular in nature (like how some RPGs have a lot of flat tables for things like XP gains), you might have an easier time using sqlite. If you want objects to take care of themselves, JSON can easily store all their information in the same structure as your C# class, which is very nice. If you instead want a very centralised data model where everything needs to have lightning-fast access to a centralised data store, sqlite is the way to go.
Both asset store links leads to Easy Save :(
Was this edited to cut out the time Unity is saving/reloadind when hitting play? I'm just wondering if I'm missing a setting that'll save me hours of my life.
Thank you so much!
What is "FileManager" please
its doesn't exist and callback an error
this tutorial is weirdly cut but what you want is in 17:30 and 17:55. just create new class FileManager and add these 2 methods
@@usz1444 thx but still some value that are unsigned even in this class .. "Path" and "File" in 17,30 doesn't exist
@@ohj6878 Same error
I was thinking playerprefs save data into file in data folder of the build.
Very helpful thanks
Does anyone know how to delete the JSON save data upon starting a new game?
You could just save an empty file on the same filepath.
so i use json to save data but i made a encryption system to encrypt the keys using some sketchy algorithm imade.. is it safe or is it easily reversable because its json
Any data on a player's computer should be considered as accessible/modifiable by the player.
Unity should buy easy save like they did with Bolt.!!! saving a lot of problems for people using the engine.
or another alternative on lootboxes, don't add them at all!
Amazing tutorial.
I also have a save system playlist series.
It covers from player-pref to Firebase.
I am currently editing the video with NodeJS as the back-end server for saving data.
Any feedback on it will be really helpful.
Am I the only one who don't have filemanager in Unity ??
It's a custom class with 2 static methods, WriteToFile and LoadFromFile. He starts his explanation at 17:25 .
Here is what it looks like.
public class FileManager {
public static bool WriteToFile(string a_filename, string a_filecontent) {
var fullPath = Path.Combine(Application.persistentDataPath, a_filename);
try {
File.WriteAllText(fullPath, a_filecontent);
return true;
} catch (Exception e) {
Debug.LogError("Fail to write to " + fullPath + " exception:" + e);
}
return false;
}
public static bool LoadFromFile(string a_filename, out string result) {
var fullPath = Path.Combine(Application.persistentDataPath, a_filename);
try {
result = File.ReadAllText(fullPath);
return true;
} catch (Exception e) {
Debug.LogError("Fail to read from " + fullPath + " exception:" + e);
result = "";
return false;
}
}
}
@@QvsTheWorld hippity hoppety that code is now my property
To understand this tutorial, you must already know 90% of what he's attempting to explain. Does not write or explain why or how most things work. Shows snippets of code with no references on what makes them work. Hopefully this helps the more advanced pupils.
found this very unclear. basicly what i got from this tutorial was "copy paste my code dont worry how to works".
Is it okay for us to only use PlayerPrefs to save data? Or we could lose it somehow?
It's not really good, involves a lot of strings and has other issues.
Why do so many people from Unity whisper at points in these videos?...
I'll be the one making Unity related videos yelling, rainbows and explosions. Mark that down.
this is some kind of spaghetti tutorial so many things not explained uncommenting all this code from earlier, no mention of interfaces, gameviewconroller etc, you dont teach people like that, you demonstrate with the most simple example to outline the flow. Then build complexity on top of that. This is a mess.
So you still use hungarian notation.... well.
Player Prefs is really dirty in windows, it will write data in the registry. Just make a Json (or XML) in any case.
Why dictionary can't be serialized?
For Assets (Item sprites...), the best way to do it is to put them in the "Resources" folder and name them with an ID system. Then check if they exist when loading your data to avoid error. It's very error prone, but it's easy and Unity offers no solution.
@@bronsonzgeb5651 Thank you for the tip, I will try that. It sound good :D (Will be easier to maintain)
Unity please make tutorials for ragdolls!
Turn off IsKinematic on your model, make sure it has a rigidbody. Ragdolls should work fine
@@pt8306 ragdoll movement?
Why is your ragdoll moving?
@@pt8306 ragdoll movement and balance scripts, i cant find any good tutorials
@@ayan3789 Normally you don't want to balance ragdolls. Instead you want to set them to kinematic movement and control them directly (with no physics), then "trigger" ragdolling by letting the rigidbody take over
Binaryformatter (ie binary files) work for me
that's probably one of the worst tutorials ever made
the guy who did the same tuto in 2014 was far far better than this one this tuto is bad he do anything
only show an already filled game its bad
I don't know if you are eating something or if it's gum, but it is super annoying and distracting. >_
Update. This awful developer no longer works at unity and went on to make the most beginner game I've ever seen. No wonder this engine and company fell through, this guy was making their tools.
With the length of the video I hope I would have learned something.
It could be shrinked down to 10 minutes with montage or maybe 5 minutes if rushed.
honestly couldnt finish the video. 7 minutes in and there was just too much smacking/swallowing/mouth noises.
This is deadAss some "draw the rest of the owl" bullshit
That mouth ASMR is really distracting when you have good headphones.
Edit: 7 minutes in and I'm clawing at my face.
this was a very poor tutorial. someone should redo this using the actual example files
Horrific tutorial, find another video. Uncommenting out code surrounded by unrelated functions looks bad. Hearing every small sound and keystroke is bad. What really blows me away is you make a reference to custom code, and explain it AT THE END OF THE SECTION. I don't think there's a nice way to put how inept that is. You breeze right past introducing FileManager to the extent I rewatched this thing from the start a few times to see if you included it, instead it was 17 minutes in. Random comments had to point this out.
Please delist this, it should not be a top result from google.