Hi! I think part of the things changed as this tutorial is from 2 years ago. As I had followed another tutorial and directly saved serialized Quaternion to json file without any issue. Well. Can't find a good tutorial like yours which talked about how to save multiple objects. That's what I needed. Thank you!
Thank you so much - I spent weeks trying to solve this problem and your tutorial fixed it! Thank you. (Just a comment that binary formatter is now not recommended - but I'm sure you're up to date on that)
Is there any other way to access the prefab of the fish without it being "drag n drop" ?? And in a case of having diferent types of fish, or just diferent objects you can add, would you have to drag and drop all used prefabs ? And would you have to create some kind of "ID" between them all so the load function can recognize which prefab it needs to instantiate ? Sorry for so many questions, im new to unity and i've been stuck on this all week, and this is the video closest to what i'm needing/doing. It already helped a lot, so thank you !!
This is the only tutorial that expands on Brackeys system. All the other tutorials are incompatible with brackey's system which i have already implemented in my game
While this is a good place to start, remember that using binary for saving data is *dangerous* as warned about on the Unity manual. Remember that if it's on a user's machine, it can be fiddled with, even as a binary. The alternative is to use the encryption, like the one provided by Newtonsoft's JSON Net which is officially endorsed by Unity. The only way to control fiddling is to store users' data remotely on your server! Don't forego security over trying to control users' actions.
i am trying to do a save system with exact same construction for my car position and rotation. I kinda made it correctly like u showed in this video but it works only for 1 prefab. how can i save location of every car that my player owns in my game ? any idea ?
Please please help me. The save system is working for me but only is the prefab is already is the scene and i am instantiating from it . But if i try to do from the prefab forlder or resources folder it doesnt load. Please help
When i play the game , its perfectly load the previous fishdata but when i Spawn more fish and quit the game and play it again its only load the spawned fishdata but not the previous fishdata, please suggest me how i can load both Spawn and Previous fishdata until i delete it. I am deleting fish On trigger enter by removing it from savesystem and destroying it .
how to save multiple user data may be 10 users. and i want to convert data into dropdown. Let me simplify this: I have a dropdown and some text fields i want to store name=XYZ, Wave survived=4, time=02:32 mints, score=34. and data would be changed according to user as his/her name and wave survied etc. i want to show all players names in a dropdown when i select a name and press a button called load data the data should be retrieved from json to textboxes. Help me please and excuse my english
I'm sorry but how can this be used with scenes ? I have a player who picks up coins. Coins are saved on the level manager. Player has health points, attack damage (effected by buffs) etc. To load the next level player hits a door that has trigger code and brings up a menu saying : next level, replay, main menu or quit. Also when you diethis comes up. So I guess what is your recommendation? Btw awsome job on your tutorials ! Next brackeys??
The code already saves to individual scenes, but it does it in a certain way, it saves objects according to each scene, it does this by adding the scene index to the path the save was created Its really simple I hope I'm not complicating it lol But can you further explain what your trying to achieve? It seems like your trying to save a certain amount of coins specific to each scene?
sorry if this is stupid question: I was getting a path error until i created the save, which i got by exiting the application (i.e. basically copy and pasting your code). Will this be a problem on build, or not that i created the files in editor, they will be there on build, and players running the "game" for the first time shouldnt experience such errors?
You know what that's a good question, that can actually cause errors The way you work around that is if there is no save found than don't load at all, so on load check if the file exists before loading it
@@kapkoder4009 another question if you dont mind. I deleted a object in my editor (outside of runtime, so it didnt get to remove on destroy), so when i went to start up the game next day it keeps saying "augment out of range", tried doing the whole "fish != null", or manually deleting the save files. And it still wont fix it, any clue? Edit: out of range on loading even though the files/and objects are deleted in game. Is there a way to also delete files on editor delete/destroy?
@@ghostghostgaming5637 if the fish has an OnDestory function you should be able to delete it in the inspector, because OnDestory will call when you delete it
@@kapkoder4009 interesting, well it did not. I notice the problem was resolved (on re testing) if i ctrl+z bring back the object back after destroying in inspector, hit play, destroy the object in runtime. then no more error.
Thank you a ton!!! However i have problem - every fish object is saved correctly on application quit, but when i load, the saved objects are doubled. For instance if i save 1 fish, on the next play there will be 2 fishes. How can i fix that ?
@@kapkoder4009 Thank you for the insights! Turned out that the error was because somehow I've added twice the Fish script and hence the 2 smelly fishes were being created :)
If I've understood this correctly each fish is saved to a seperate file on the disk. Out of curiosity, is it possible to then merge (and unmerge at the other end) all of these into a single file without using 3rd party compression software? This is an amazing video by the way, I've been struggling to get my head around this for quite some time
We’ll I would just put all the files into a folder that you create, but idk if you can merge the save, I never tried it, because every save file is unique and i don’t see a reason to merge them, we Serialize each object (fish) separately in the for loop and that seems good
@@kapkoder4009 Thanks for the quick reply. I was thinking it would be easier to move/share saves with a single file, but now that I think of it you can share/move a folder just as easily as you can a single file.
@@kapkoder4009 I think there must be a standard simpler way to do the save and load system. Take skyrim for instance, it's an open world game and what it saves are not just some player status and checkpoint. When you load into the game, you go into the place where you killed the enemies, the bodies will remain there. And all the different status of the NPCs in the world. But when you check the save file location, it has only one file. Nearly all the games we can think of they only got one save file.
You can still use it if you instantiate your objects in another class, the only difference is that you need to re-instantiate the objects on awake in the SaveSystem.cs again
had similar issue, to solve it what i did is make a public int buildingIndex; in all my buildings (their script is called BuildingIds) now go to saveSystem change [SerializeField] BuildingIds buildingPrefab; to [SerializeField] BuildingIds []buildingPrefab; basicly an array of prefabs now go to your load function change BuildingIds building = Instantiate(buildingPrefab,position,Quaternion.identity); to BuildingIds building = Instantiate(buildingPrefab[data.buildingIndex],position,Quaternion.identity); essentially buildingIndex is your prefab ID when u spawn the game object you spawn it based on the ID it have in the array (make sure you put them in order in inspector) Note: i made this within 15 min of watching the video so their might be bugs , errors, better way to make this but so far it worked for me good luck!
@@AzzeddineXT You are incredible thank you! I know it's been a while, but if you remember if any bugs DID come up, can you let me know? I think I'll use this method in the future, and I'd like to be ready in case anything comes up.
What's the best way to save a status data (coins, highscore), a achievements data (unlockeds, current progress) and a skins data (purchased, equipped) ? With this tutorial i guess have to make a "Type"Data for each data which can be saved, this is correctly ? If yes how i can make this in the right way?
You can watch this video: ruclips.net/video/Bv-Qie4ISWg/видео.html In this one you can use one class to save any type of data for you instead of making a save function for every type of data you want to save... This way is truly much more productive And than you can make a "PlayerData" class and put the coins highscore skins achievements data in there and throw it in the SaveSystem in the video and save it
hey man, saving works fantastic and in fact saved my entire project. I've even expanded on it since. However, while im coming around to the end of this games development, i want to add a way to delete a file. Not all saved data that relates to the game, just a specific scenes data. Any ideas?
Hi can anyone help me with this: The problem is that the first fish Filestream text file (not the fishCount) always gets empty by itself after changing scene or pressing another button or sometimes it gets empty by just waiting a bit and reseting unity. I get this error: "SerializationException: Attempting to deserialize an empty stream" and im not sure if the stream gets empty while saving or loading. It lways happens when i reset the scene or the game and the fishCount file also gets empty while there is more than 1 fish stream in the same folder. It always happenes to the first fish FileStream and if i delete the FileStream from the folder and create another one, the same thing happenes. If you know the answer please tell me.
Hi, i im stuck and cant solve this problem: I run the game normally and everything is ok, but all of a sudden when i change the scene or reset the game, the fishCount resets to 0 by itself even though there is more than one fish created. And because of that i cant spawn the same fished that were there before. Edit: In the fish prefab, i have a OnDestroy method that deletes itself(the fish) from the fish list. And on the save system, we save the fishcount to binary by serializing fishList.Count. I think this is the reason why the fishcount becomes 0 but i dont know how to solve it and have the OnDestroy method on at the same time. If you know the answer please tell me :)
I remember having a problem like that... Oohh wait I think I remember Keep your fishes OnDestory() but have your SaveSystem Save() OnApplicationQuit() because onApplicationQuit is called before onDestroy therefor whatever onDestory does won't affect the save file Take a look at unity's execution order: docs.unity3d.com/Manual/ExecutionOrder.html You can see here in the "Decommissioning" phase onDestroy is called AFTER onApplicationQuit making onApplicationQuit the safest way to save BUT if your making a game for Android use onApplicationPause like this: void OnApplicationPause(bool pause) { if (pause) { Save(); } } Make sure you hit tab to finish the method so you don't misspell the parameter or else it won't work Let me know if this was the solution, I don't think it is because we already uses onApplicationQuit in the video?
@@kapkoder4009 i tried to put the "OnApplicationPause" method because my game is for android but still dont wrok :( I dont know why this happenes, it's been a week and i tried mostly everything. Is there anything else i can do to solve this problem, i hope that it wont take a long time to fix it.
@@kapkoder4009 In my scripts the NP(or notepad) is the fish in your video. I've also added some extra data for my game object so it is not all the same as the video. Note: I wrote some words all capitalized to make it easy to read(I'm not shouting) :) Please tell me if there is anything else I have to do or send :) THE FISHDATA SCRIPT: using UnityEngine; [System.Serializable] public class NPData_Script { public float[] position = new float[3]; public string NPname; public string FavouriteOn; public NPData_Script(NotePad notePad) { Vector3 NPpos = notePad.transform.position; position = new float[3] { NPpos.x, NPpos.y, NPpos.z }; NPname = notePad.NPname.text; FavouriteOn = notePad.favouriteOn; } } THE FISH SCRIPT(mine is called "NotePad"): using UnityEngine; using TMPro; using UnityEngine.UI; public class NotePad : MonoBehaviour { public TMP_InputField NPname; public Button FavouriteBtn; private bool on = false; public string favouriteOn = "Yes"; private void Awake() { SaveSystem_Script.notePads.Add(this); } private void OnDestroy() { SaveSystem_Script.notePads.Remove(this); } private void Start() { if (favouriteOn == "Yes") { FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 255); on = true; } else if (favouriteOn == "No") { FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 120); on = false; } } public void Set_Favourite_OnOff() { if (!on) { favouriteOn = "Yes"; FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 255); on = true; } else { favouriteOn = "No"; FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 120); on = false; } } } THE SAVESYSTEM SCRIPT: using System.Collections.Generic; using UnityEngine; using System.Runtime.Serialization.Formatters.Binary; using UnityEngine.SceneManagement; using System.IO; public class SaveSystem_Script : MonoBehaviour { [SerializeField] NotePad notePadPrefab; public static List notePads = new List(); const string NP_Sub = "/notePad"; const string NP_Count_Sub = "/notePad.count"; private void Awake() { Load_NotePad(); } private void OnApplicationPause(bool pause) { if (pause) { Save_NotePad(); } } void Save_NotePad() { BinaryFormatter formatter = new BinaryFormatter(); string path = Application.persistentDataPath + NP_Sub + SceneManager.GetActiveScene().buildIndex; string countPath = Application.persistentDataPath + NP_Count_Sub + SceneManager.GetActiveScene().buildIndex; FileStream countStream = new FileStream(countPath, FileMode.Create); formatter.Serialize(countStream, notePads.Count); countStream.Close(); for (int i = 0; i < notePads.Count; i++) { FileStream stream = new FileStream(path + i, FileMode.Create); NPData_Script data = new NPData_Script(notePads[i]); formatter.Serialize(stream, data); stream.Close(); } } void Load_NotePad() { BinaryFormatter formatter = new BinaryFormatter(); string path = Application.persistentDataPath + NP_Sub + SceneManager.GetActiveScene().buildIndex; string countPath = Application.persistentDataPath + NP_Count_Sub + SceneManager.GetActiveScene().buildIndex; int NPCount = 0; if (File.Exists(countPath)) { FileStream countStream = new FileStream(countPath, FileMode.Open); NPCount = (int)formatter.Deserialize(countStream); countStream.Close(); print("NP count " + NPCount); } else print("count path not found"); for (int i = 0; i < NPCount; i++) { if (File.Exists(path + i)) { FileStream stream = new FileStream(path + i, FileMode.Open); NPData_Script data = formatter.Deserialize(stream) as NPData_Script; stream.Close(); Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]); NotePad notePad = Instantiate(notePadPrefab, position, Quaternion.identity); notePad.transform.SetParent(GameObject.FindGameObjectWithTag("Respawn").transform); notePad.transform.localScale = new Vector3(1f, 1f, 1f); notePad.NPname.text = data.NPname; notePad.favouriteOn = data.FavouriteOn; } else print("Path not found in " + path + i); } } }
@@Driverbazona Okay, I read all of your code and it all looks good! no common mistakes were made, but I know what your issue is, its not the code, its the lack of it so right now your only using OnApplicationPause to save but you should use both OnApplicationPause AND OnApplicationQuit, because sure, if you quit the game your pause function will return true and your game will save, but what about when you switch scenes? OnApplicationPause won't return true This is where you add OnApplicationQuit to the equation, but call it in a way that avoids saving twice in certain scenarios, like this: bool saved = false; //THIS IS A BOOL TO CHECK if you already saved :) void OnApplicationQuit() { if (!saved) { Save(); //Now this is probably what's gonna save your bottom 😉 saved = true; } } void OnApplicationPause(bool pause) { if (pause && !saved) { Save(); saved = true; } } let me know if this worked! and also you don't have to write "private" in a function because void by itself is already private, but you can keep that if its your preference, and you don't need to put _Script at the end of your script names, but then again! it's all preference!
Can anyone help me with this: I wrote "[SerializeField] Fish fishPrefab;" same as in 15:50, but when i go to unity i cant assign/put the prefab. If you know the answer please tell me.
Yep that was the problem Thank u so much this took me a lot of time and i thought it would take more but then i saw your video and did it, keep up your greate work and your amazing videos😊
You can simply create Scriptable Objects (i have a tutorial on that in my tutorials Playlist scripted objects are super easy to use) and since you can't serialize scripted object im going to create a tutorial on how to save scripted objects so that you can have different fish persist between loads
Hey! I came across your video after finishing Brackeys tutorial. Works great, everything saves and loads. But how do I now delete the binary file, for example by pressing "New Game" in the menu? EDIT: Also after deleting the file, create a new file in order to start the game with the default values (example 3 hearts and start location)
2 years too late but I used this. string[] filePaths = Directory.GetFiles(Application.persistentDataPath); foreach (string filePath in filePaths) File.Delete(filePath); Then make sure to clear your SaveSystem list. Fishes.Clear(); Keep in mind this will delete every file in your persistentDataPath. If you only want to delete specific files you'll have to save them to specific directories and GetFiles from that directory instead of the entire persistentDataPath.
Thank you! I now understand this better as I was a clear beginner when I wrote this comment, however I ended up using an asset instead to manage my save system 😊@@3bomb
Can anyone help me with this: How can i delete the FileStream of a fish when it is deleted? I have a button and when i press it, it deletes the fish but i dont know how to get the FileStream of this fish and delete it too. If you know the answer please tell me :)
You don't have to delete the file stream Just go on your fish and add a OnDestroy() { SaveSystem.fishes.Remove(this) //this as in fish } Now I don't remember exactly what the classes are called but I think that's how you remove it from the list
I know how to remove it from the list but i mean that when i delete the object from unity, the text file stays in unity folders and if the player creates a lot of fishes and then delete them, the text files will stay in the path we put.
@@Driverbazona Here's how to delete all save data 1. You can do it manually by navigating through your folders and finding the saves 2. You can delete all your saves through code For 1. On windows you go to your search bar next to your windows button and search "%appdata% > AppData > LocalLow > Your company name (if not set its probably "DefaultCompany") > Your project name, and there you should see all your saved files On Mac I found it by going to your main home (which is usually the name of the user) and in there press (Shift + Command + . (period key)) to reveal hidden files, than you should see Library and go to > Application support > You company name ("Default Company" by default) > Your project name > and there's all your saves 2. Which is the way i think you probably want to do it is... Through code! Here's how First of all you should have made a "/saves" folder where you put all your saves so that if you just delete that one folder it deletes everything, you'll find a reference of how to put everything in a saves folder in this video ruclips.net/video/Bv-Qie4ISWg/видео.html Example starts @ 6:57 and ends at 8:22 but continue watching if your confused Than like this you can just: void DeleteAllSaveData() { string path = yourPath (you know what your path is) DirectoryInfo directory = new DirectoryInfo(path) //Now delete this found directory directory.Delete(true) //Now re-create the directory Directory.CreateDirectory(path) } But until setting up the /saves folder you still need to delete all those random files! Where not going to do that with code because you could just manually delete them and than implement that /saves sub file and start deleting them that way... I though I could show you how to delete all the random files with code, it won't be be pretty 😅 (I've done it before you just make a bunch of for loops finding the files by name)
Either find the files on your system or delete your saves directory (file) with code if you even put it in a directory, I dont think we did in this video If you want an example of using directories watch this video, the save system in it puts all the saves in one main file Directory example starts at 5:36 ruclips.net/video/Bv-Qie4ISWg/видео.html Or you can go directly in your system and find it and delete it On mac: press shift + command + period to show hidden files and go to Library > Application Support > Your games company name and you'll find the saves in there On windows: I dont have a windows you should probably search this yourself but ill try off the top of my head In your windows search bar or in files just search "%appdata%" and snoop around in there for your game lol Hope this helped
@@kapkoder4009i know how to delete a file from the system. I mean, how the player can delete the data ingame? Isn't there a function like, Destroy (File) ;?
@@cake8242 you can make the function This function will delete a file and recreate it (as a new empty file) Keep in mind you need this namespace Which is I think the only one you need for this in particular using System.IO; void DeleteSave() { string path = Application.persistentDataPath + "/pathKey/"; DirectoryInfo directory = new DirectoryInfo(path); directory.Delete() Directory.CreateDirectory(path) }
Hey, any way to make this save a list of Class Object? So I am making a task system and I don't want to make a new file for every task. How do I serialize a list of objects with this method and then load it? Also, I will be rewriting the file with this list of objects. So should I be appending it or just filemode create with my serialized list will overwrite over everything?
Great Video! I am new to coding and can't seem to save the rotation. Could you provide us with how to add rotation to the save? Attached are parts of the code I added/modified. Thanks! Save System: Quaternion rotation = Quaternion.Euler(data.rotation[0], data.rotation[1], data.rotation[2]); Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]); Fish fish = Instantiate(fishPrefab, position, rotation); Fishdata: public float[] rotation; public FishData(Fish fish) { Quaternion fishrot = fish.transform.rotation; rotation = new float[] { fishrot.x, fishrot.y, fishrot.z }; }
Hey, don't use Quaternions or modify they're values individually as they're quite complicated Instead just save the rotation as a Vector2 or 3 and set the transform.eulerAngles = savedVectorRotation Not the transform.rotation, when accessing the objects rotation grab its .eulerAngles, not its .rotation Example: float[] rotation; //you cant save Quaternions or vectors so store the value in a float array void YourFunction() { Vector3 fishRot = fish.transform.eulerAngles rotation = new float[] { fishRot.x, fishRot.y, fishRot.z } } And this is all off the top of my head so don't quote me on it lol And when loading the rotation just take the saved float array and set the fishes eulerAngles to the elements on that float array you saved Long story short just use the eulerAngles instead lol
@@vrgo8279 awesome! Funny thing is I actually ran into the same problem myself a while ago, I was saving and setting the rotation as Quaternion and it would always load wrong, like I save a certain value and it would load a completely different value lol
@@kapkoder4009 I have been trying to save 2 different objects using the same savesystem. Do you know what I would need to change in the scripts in order to save more than one kind of object. Thank you for your help!
@@vrgo8279 well I had to do that... I had fish and decorations Decorations needed the position, size and stuff to be saved, basically like a fish So I made a separate data class (DecorationData.cs) Have each decoration put themselves into a list of decorations on the SAME SAVESYSTEM.cs (sorry I'm not yelling) so basically, when it was time to save, the save system iterated through all the decorations (just like the fish) saved whatever was needed (see? Like the separate DecorationData.cs class) and loaded them as usual Long story short, yes you need separate data classes but you need the savesytem to do all the work with the data If this didn't help maybe you could further elaborate on your dilemma and I could propose a solution because that's what I always do i guess lol
Well, everything should’ve worked idk did you tweak something with the load function? You have to make sure your spawning a prefab and you have a reference to one in the inspector
Does not work Path Not Found InC:/Users/Dell/AppData/LocalLow/DefaultCompany/Project_Reject/item0 UnityEngine.Debug:LogError(Object) SaveSystem:LoadItem() (at Assets/Scripts/SaveSystem.cs:61) SaveSystem:Awake() (at Assets/Scripts/SaveSystem.cs:18)
I've given up on life, same code as you and nothing spawns Save System code: public class SaveSystem : MonoBehaviour { [Header("Prefabs")] [SerializeField] Furniture furnitureprefab; public static List furnitureList = new List(); const string FurniturePath = "/furniture"; const string FurnitureCountPath = "/furniture.count"; public void Awake() { LoadFurniture(); } public void OnApplicationQuit() { SaveFurniture(); } public void SaveFurniture() { BinaryFormatter formatter = new BinaryFormatter(); string path = Application.persistentDataPath + FurniturePath + SceneManager.GetActiveScene().buildIndex; string countPath = Application.persistentDataPath + FurnitureCountPath + SceneManager.GetActiveScene().buildIndex; FileStream countStream = new FileStream(countPath, FileMode.Create); formatter.Serialize(countStream, furnitureList.Count); countStream.Close(); for (int i = 0; i < furnitureList.Count; i++) { FileStream stream = new FileStream(path + i, FileMode.Create); FurnitureData data = new FurnitureData(furnitureList[i]); formatter.Serialize(stream, data); stream.Close(); } } public void LoadFurniture() { BinaryFormatter formatter = new BinaryFormatter(); string path = Application.persistentDataPath + FurniturePath + SceneManager.GetActiveScene().buildIndex; string countPath = Application.persistentDataPath + FurnitureCountPath + SceneManager.GetActiveScene().buildIndex; int FurnitureCount = 0; if (File.Exists(countPath)) { FileStream countStream = new FileStream(countPath, FileMode.Open); FurnitureCount = (int)formatter.Deserialize(countStream); countStream.Close(); } else { Debug.LogError("Path not found in " + countPath); } for (int i = 0; i < furnitureList.Count; i++) { if (File.Exists(path + i)) { FileStream stream = new FileStream(path + i, FileMode.Open); FurnitureData data = formatter.Deserialize(stream) as FurnitureData; stream.Close(); Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]); Furniture furniture = Instantiate(furnitureprefab, position, Quaternion.identity); } else { Debug.LogError("Path not found in " + (path + i)); } } } }my "fishdata" - i only want to save position [Serializable] public class FurnitureData { public float[] position; public FurnitureData(Furniture furniture) { Vector3 furniturePos = furniture.transform.position; position = new float[] { furniturePos.x, furniturePos.y, furniturePos.z }; } } my "fish" class - there's no functionality on this besides adding it to the list because things are handled in other scripts. public class Furniture : MonoBehaviour { public void Awake() { SaveSystem.furnitureList.Add(this); } }
I know its been 3 years, but bro casually saved my bachelors thesis, bless you
You know its a good day when kap koder uploads
Wow. I turned the bell on a while ago and RIGHT when you uploaded, it's just what I needed as part of my building game! Great content!
I'm happy this came to your help! 😊
Thank you for deciding to take the time to make this highly specific tutorial. This is exactly what I needed :)
same
Hi! I think part of the things changed as this tutorial is from 2 years ago. As I had followed another tutorial and directly saved serialized Quaternion to json file without any issue. Well. Can't find a good tutorial like yours which talked about how to save multiple objects. That's what I needed. Thank you!
this ... saved me. you actually have no idea! thankyou!
i think i found a perfect tutorial for my use
ill see in some time
Thank you so much - I spent weeks trying to solve this problem and your tutorial fixed it! Thank you.
(Just a comment that binary formatter is now not recommended - but I'm sure you're up to date on that)
I actually haven’t coded in a while… what happened? Was it exploited or considered unsafe now?
@@kapkoder4009 yes
Thanks for this, it was handy. I lol'd at the Joe Rogan bit.
Really a very successful tutorial was clear and understandable thank you very much...
Bro you saved my life... Thanks a lot!
Is there any other way to access the prefab of the fish without it being "drag n drop" ?? And in a case of having diferent types of fish, or just diferent objects you can add, would you have to drag and drop all used prefabs ? And would you have to create some kind of "ID" between them all so the load function can recognize which prefab it needs to instantiate ? Sorry for so many questions, im new to unity and i've been stuck on this all week, and this is the video closest to what i'm needing/doing. It already helped a lot, so thank you !!
This is the only tutorial that expands on Brackeys system. All the other tutorials are incompatible with brackey's system which i have already implemented in my game
While this is a good place to start, remember that using binary for saving data is *dangerous* as warned about on the Unity manual. Remember that if it's on a user's machine, it can be fiddled with, even as a binary. The alternative is to use the encryption, like the one provided by Newtonsoft's JSON Net which is officially endorsed by Unity.
The only way to control fiddling is to store users' data remotely on your server! Don't forego security over trying to control users' actions.
What if i have a Object wich starts in the scene how can i manage that?
how can I save updated Boolean value in this??
i am trying to do a save system with exact same construction for my car position and rotation. I kinda made it correctly like u showed in this video but it works only for 1 prefab. how can i save location of every car that my player owns in my game ? any idea ?
Please please help me. The save system is working for me but only is the prefab is already is the scene and i am instantiating from it . But if i try to do from the prefab forlder or resources folder it doesnt load. Please help
thank you for this video. its very helpful. but something stuck in my head, what if there were more prefabs? for example about 20 or more?
When i play the game , its perfectly load the previous fishdata but when i Spawn more fish and quit the game and play it again its only load the spawned fishdata but not the previous fishdata, please suggest me how i can load both Spawn and Previous fishdata until i delete it. I am deleting fish On trigger enter by removing it from savesystem and destroying it .
Is the new objects your spawning adding itself to the saves list?
Hi! For some reason, if i create a world, join in, then quit, in the menu duplicates that world prefab (it’s a multiplayer game)
wow, love this video. will try to save the binary to mysql tho😟
For me it only loads one fish and not all... what is the problem???
Nice videos keep it going!
It worked! thanks
how to save multiple user data may be 10 users.
and i want to convert data into dropdown.
Let me simplify this:
I have a dropdown and some text fields
i want to store name=XYZ, Wave survived=4, time=02:32 mints, score=34.
and data would be changed according to user as his/her name and wave survied etc.
i want to show all players names in a dropdown when i select a name and press a button called load data the data should be retrieved from json to textboxes.
Help me please and excuse my english
Okay so, how do you load a fish that has been destroyed?
I'm sorry but how can this be used with scenes ?
I have a player who picks up coins. Coins are saved on the level manager. Player has health points, attack damage (effected by buffs) etc. To load the next level player hits a door that has trigger code and brings up a menu saying : next level, replay, main menu or quit. Also when you diethis comes up.
So I guess what is your recommendation? Btw awsome job on your tutorials ! Next brackeys??
The code already saves to individual scenes, but it does it in a certain way, it saves objects according to each scene, it does this by adding the scene index to the path the save was created
Its really simple I hope I'm not complicating it lol
But can you further explain what your trying to achieve?
It seems like your trying to save a certain amount of coins specific to each scene?
sorry if this is stupid question: I was getting a path error until i created the save, which i got by exiting the application (i.e. basically copy and pasting your code). Will this be a problem on build, or not that i created the files in editor, they will be there on build, and players running the "game" for the first time shouldnt experience such errors?
You know what that's a good question, that can actually cause errors
The way you work around that is if there is no save found than don't load at all, so on load check if the file exists before loading it
@@kapkoder4009 another question if you dont mind. I deleted a object in my editor (outside of runtime, so it didnt get to remove on destroy), so when i went to start up the game next day it keeps saying "augment out of range", tried doing the whole "fish != null", or manually deleting the save files. And it still wont fix it, any clue?
Edit: out of range on loading even though the files/and objects are deleted in game. Is there a way to also delete files on editor delete/destroy?
@@ghostghostgaming5637 if the fish has an OnDestory function you should be able to delete it in the inspector, because OnDestory will call when you delete it
@@kapkoder4009 interesting, well it did not. I notice the problem was resolved (on re testing) if i ctrl+z bring back the object back after destroying in inspector, hit play, destroy the object in runtime. then no more error.
@@ghostghostgaming5637 huh interesting
It could have been that you didn't restart the game after you saved your script?
i want to save my shop system how to ? help me!
Thank you a ton!!!
However i have problem - every fish object is saved correctly on application quit, but when i load, the saved objects are doubled. For instance if i save 1 fish, on the next play there will be 2 fishes. How can i fix that ?
Make sure that the objects your saving has a function to remove itself from the saves list in the OnDestroy() callback function
@@kapkoder4009 Thank you for the insights!
Turned out that the error was because somehow I've added twice the Fish script and hence the 2 smelly fishes were being created :)
brooo thank you sooo much
Thank You!
If I've understood this correctly each fish is saved to a seperate file on the disk. Out of curiosity, is it possible to then merge (and unmerge at the other end) all of these into a single file without using 3rd party compression software?
This is an amazing video by the way, I've been struggling to get my head around this for quite some time
We’ll I would just put all the files into a folder that you create, but idk if you can merge the save, I never tried it, because every save file is unique and i don’t see a reason to merge them, we Serialize each object (fish) separately in the for loop and that seems good
@@kapkoder4009 Thanks for the quick reply. I was thinking it would be easier to move/share saves with a single file, but now that I think of it you can share/move a folder just as easily as you can a single file.
@@kapkoder4009 I think there must be a standard simpler way to do the save and load system. Take skyrim for instance, it's an open world game and what it saves are not just some player status and checkpoint. When you load into the game, you go into the place where you killed the enemies, the bodies will remain there. And all the different status of the NPCs in the world. But when you check the save file location, it has only one file. Nearly all the games we can think of they only got one save file.
How can i implement this method for objects instantiated in different class. Because I already have a class for instantiation. Please help😭
You can still use it if you instantiate your objects in another class, the only difference is that you need to re-instantiate the objects on awake in the SaveSystem.cs again
Awesome 👍👍
it might be obvious but I'm really bad at unity so how can I save multiple objects with this script?
had similar issue, to solve it what i did is make a
public int buildingIndex;
in all my buildings (their script is called BuildingIds)
now go to saveSystem
change [SerializeField] BuildingIds buildingPrefab; to
[SerializeField] BuildingIds []buildingPrefab;
basicly an array of prefabs
now go to your load function
change BuildingIds building = Instantiate(buildingPrefab,position,Quaternion.identity); to
BuildingIds building = Instantiate(buildingPrefab[data.buildingIndex],position,Quaternion.identity);
essentially buildingIndex is your prefab ID
when u spawn the game object you spawn it based on the ID it have in the array (make sure you put them in order in inspector)
Note: i made this within 15 min of watching the video so their might be bugs , errors, better way to make this
but so far it worked for me
good luck!
@@AzzeddineXT You are incredible thank you! I know it's been a while, but if you remember if any bugs DID come up, can you let me know? I think I'll use this method in the future, and I'd like to be ready in case anything comes up.
mine works perfectly in editor but when i make an android build it doesnt work, anyone know what should be?
On android you need to save on application pause because if you don’t completely shut off an app on android than it won’t call OnApplicationQuit
What's the best way to save a status data (coins, highscore), a achievements data (unlockeds, current progress) and a skins data (purchased, equipped) ? With this tutorial i guess have to make a "Type"Data for each data which can be saved, this is correctly ? If yes how i can make this in the right way?
You can watch this video:
ruclips.net/video/Bv-Qie4ISWg/видео.html
In this one you can use one class to save any type of data for you instead of making a save function for every type of data you want to save...
This way is truly much more productive
And than you can make a "PlayerData" class and put the coins highscore skins achievements data in there and throw it in the SaveSystem in the video and save it
@@kapkoder4009 very thanks man i gonna jump into this tutorial
hey man, saving works fantastic and in fact saved my entire project. I've even expanded on it since. However, while im coming around to the end of this games development, i want to add a way to delete a file. Not all saved data that relates to the game, just a specific scenes data. Any ideas?
You can search for the files string name (full path and name you attached to the path) and delete it, pretty straightforward
@@kapkoder4009 how would this look like implemented in code?
Hi can anyone help me with this:
The problem is that the first fish Filestream text file (not the fishCount) always gets empty by itself after changing scene or pressing another button or sometimes it gets empty by just waiting a bit and reseting unity.
I get this error: "SerializationException: Attempting to deserialize an empty stream"
and im not sure if the stream gets empty while saving or loading.
It lways happens when i reset the scene or the game and the fishCount file also gets empty while there is more than 1 fish stream in the same folder.
It always happenes to the first fish FileStream and if i delete the FileStream from the folder and create another one, the same thing happenes.
If you know the answer please tell me.
I think you need to remove the fish from the saves list when you destroy it
Yep, thanks that was it :)
forgot the fish class
Hi, i im stuck and cant solve this problem:
I run the game normally and everything is ok, but all of a sudden when i change the scene or reset the game, the fishCount resets to 0 by itself even though there is more than one fish created. And because of that i cant spawn the same fished that were there before.
Edit:
In the fish prefab, i have a OnDestroy method that deletes itself(the fish) from the fish list. And on the save system, we save the fishcount to binary by serializing fishList.Count. I think this is the reason why the fishcount becomes 0 but i dont know how to solve it and have the OnDestroy method on at the same time.
If you know the answer please tell me :)
I remember having a problem like that...
Oohh wait I think I remember
Keep your fishes OnDestory() but have your SaveSystem Save() OnApplicationQuit() because onApplicationQuit is called before onDestroy therefor whatever onDestory does won't affect the save file
Take a look at unity's execution order:
docs.unity3d.com/Manual/ExecutionOrder.html
You can see here in the "Decommissioning" phase onDestroy is called AFTER onApplicationQuit making onApplicationQuit the safest way to save
BUT
if your making a game for Android use onApplicationPause like this:
void OnApplicationPause(bool pause)
{
if (pause)
{
Save();
}
}
Make sure you hit tab to finish the method so you don't misspell the parameter or else it won't work
Let me know if this was the solution, I don't think it is because we already uses onApplicationQuit in the video?
@@kapkoder4009 i tried to put the "OnApplicationPause" method because my game is for android but still dont wrok :(
I dont know why this happenes, it's been a week and i tried mostly everything. Is there anything else i can do to solve this problem, i hope that it wont take a long time to fix it.
@@Driverbazona send me your code
@@kapkoder4009
In my scripts the NP(or notepad) is the fish in your video. I've also added some extra data for my game object so it is not all the same as the video.
Note: I wrote some words all capitalized to make it easy to read(I'm not shouting) :)
Please tell me if there is anything else I have to do or send :)
THE FISHDATA SCRIPT:
using UnityEngine;
[System.Serializable]
public class NPData_Script
{
public float[] position = new float[3];
public string NPname;
public string FavouriteOn;
public NPData_Script(NotePad notePad)
{
Vector3 NPpos = notePad.transform.position;
position = new float[3] { NPpos.x, NPpos.y, NPpos.z };
NPname = notePad.NPname.text;
FavouriteOn = notePad.favouriteOn;
}
}
THE FISH SCRIPT(mine is called "NotePad"):
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class NotePad : MonoBehaviour
{
public TMP_InputField NPname;
public Button FavouriteBtn;
private bool on = false;
public string favouriteOn = "Yes";
private void Awake()
{
SaveSystem_Script.notePads.Add(this);
}
private void OnDestroy()
{
SaveSystem_Script.notePads.Remove(this);
}
private void Start()
{
if (favouriteOn == "Yes")
{ FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 255); on = true; }
else if (favouriteOn == "No")
{ FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 120); on = false; }
}
public void Set_Favourite_OnOff()
{
if (!on)
{
favouriteOn = "Yes";
FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 255);
on = true;
}
else
{
favouriteOn = "No";
FavouriteBtn.GetComponent().color = new Color32(255, 255, 255, 120);
on = false;
}
}
}
THE SAVESYSTEM SCRIPT:
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine.SceneManagement;
using System.IO;
public class SaveSystem_Script : MonoBehaviour
{
[SerializeField] NotePad notePadPrefab;
public static List notePads = new List();
const string NP_Sub = "/notePad";
const string NP_Count_Sub = "/notePad.count";
private void Awake()
{
Load_NotePad();
}
private void OnApplicationPause(bool pause)
{
if (pause)
{
Save_NotePad();
}
}
void Save_NotePad()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + NP_Sub + SceneManager.GetActiveScene().buildIndex;
string countPath = Application.persistentDataPath + NP_Count_Sub + SceneManager.GetActiveScene().buildIndex;
FileStream countStream = new FileStream(countPath, FileMode.Create);
formatter.Serialize(countStream, notePads.Count);
countStream.Close();
for (int i = 0; i < notePads.Count; i++)
{
FileStream stream = new FileStream(path + i, FileMode.Create);
NPData_Script data = new NPData_Script(notePads[i]);
formatter.Serialize(stream, data);
stream.Close();
}
}
void Load_NotePad()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + NP_Sub + SceneManager.GetActiveScene().buildIndex;
string countPath = Application.persistentDataPath + NP_Count_Sub + SceneManager.GetActiveScene().buildIndex;
int NPCount = 0;
if (File.Exists(countPath))
{
FileStream countStream = new FileStream(countPath, FileMode.Open);
NPCount = (int)formatter.Deserialize(countStream);
countStream.Close();
print("NP count " + NPCount);
}
else
print("count path not found");
for (int i = 0; i < NPCount; i++)
{
if (File.Exists(path + i))
{
FileStream stream = new FileStream(path + i, FileMode.Open);
NPData_Script data = formatter.Deserialize(stream) as NPData_Script;
stream.Close();
Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]);
NotePad notePad = Instantiate(notePadPrefab, position, Quaternion.identity);
notePad.transform.SetParent(GameObject.FindGameObjectWithTag("Respawn").transform);
notePad.transform.localScale = new Vector3(1f, 1f, 1f);
notePad.NPname.text = data.NPname;
notePad.favouriteOn = data.FavouriteOn;
}
else
print("Path not found in " + path + i);
}
}
}
@@Driverbazona Okay, I read all of your code and it all looks good! no common mistakes were made, but I know what your issue is, its not the code, its the lack of it
so right now your only using OnApplicationPause to save but you should use both OnApplicationPause AND OnApplicationQuit, because sure, if you quit the game your pause function will return true and your game will save, but what about when you switch scenes? OnApplicationPause won't return true
This is where you add OnApplicationQuit to the equation, but call it in a way that avoids saving twice in certain scenarios, like this:
bool saved = false; //THIS IS A BOOL TO CHECK if you already saved :)
void OnApplicationQuit()
{
if (!saved)
{
Save(); //Now this is probably what's gonna save your bottom 😉
saved = true;
}
}
void OnApplicationPause(bool pause)
{
if (pause && !saved)
{
Save();
saved = true;
}
}
let me know if this worked!
and also you don't have to write "private" in a function because void by itself is already private, but you can keep that if its your preference, and you don't need to put _Script at the end of your script names, but then again! it's all preference!
Can anyone help me with this:
I wrote "[SerializeField] Fish fishPrefab;" same as in 15:50, but when i go to unity i cant assign/put the prefab.
If you know the answer please tell me.
Do you have a prefab that has a Fish.cs script on it? If not than you can't put it in that fish field
Yep that was the problem
Thank u so much this took me a lot of time and i thought it would take more but then i saw your video and did it, keep up your greate work and your amazing videos😊
How can I use this system with differents kind of fish ?
You can simply create Scriptable Objects (i have a tutorial on that in my tutorials Playlist scripted objects are super easy to use) and since you can't serialize scripted object im going to create a tutorial on how to save scripted objects so that you can have different fish persist between loads
Hey! I came across your video after finishing Brackeys tutorial. Works great, everything saves and loads. But how do I now delete the binary file, for example by pressing "New Game" in the menu?
EDIT: Also after deleting the file, create a new file in order to start the game with the default values (example 3 hearts and start location)
I'd have to look at what I did in the video to catch up on what your saying and give you the best solution
I'll reply when I get off work *3-5h
@@kapkoder4009 Very much appreciated :)
Hey, any solution for this?
2 years too late but I used this.
string[] filePaths = Directory.GetFiles(Application.persistentDataPath);
foreach (string filePath in filePaths)
File.Delete(filePath);
Then make sure to clear your SaveSystem list.
Fishes.Clear();
Keep in mind this will delete every file in your persistentDataPath. If you only want to delete specific files you'll have to save them to specific directories and GetFiles from that directory instead of the entire persistentDataPath.
Thank you! I now understand this better as I was a clear beginner when I wrote this comment, however I ended up using an asset instead to manage my save system 😊@@3bomb
You are the best
Can anyone help me with this:
How can i delete the FileStream of a fish when it is deleted? I have a button and when i press it, it deletes the fish but i dont know how to get the FileStream of this fish and delete it too.
If you know the answer please tell me :)
You don't have to delete the file stream
Just go on your fish and add a
OnDestroy()
{
SaveSystem.fishes.Remove(this)
//this as in fish
}
Now I don't remember exactly what the classes are called but I think that's how you remove it from the list
I know how to remove it from the list but i mean that when i delete the object from unity, the text file stays in unity folders and if the player creates a lot of fishes and then delete them, the text files will stay in the path we put.
@@Driverbazona Here's how to delete all save data
1. You can do it manually by navigating through your folders and finding the saves
2. You can delete all your saves through code
For 1. On windows you go to your search bar next to your windows button and search "%appdata% > AppData > LocalLow > Your company name (if not set its probably "DefaultCompany") > Your project name, and there you should see all your saved files
On Mac I found it by going to your main home (which is usually the name of the user) and in there press (Shift + Command + . (period key)) to reveal hidden files, than you should see Library and go to > Application support > You company name ("Default Company" by default) > Your project name > and there's all your saves
2. Which is the way i think you probably want to do it is... Through code! Here's how
First of all you should have made a "/saves" folder where you put all your saves so that if you just delete that one folder it deletes everything, you'll find a reference of how to put everything in a saves folder in this video
ruclips.net/video/Bv-Qie4ISWg/видео.html
Example starts @ 6:57 and ends at 8:22 but continue watching if your confused
Than like this you can just:
void DeleteAllSaveData()
{
string path = yourPath (you know what your path is)
DirectoryInfo directory = new DirectoryInfo(path)
//Now delete this found directory
directory.Delete(true)
//Now re-create the directory
Directory.CreateDirectory(path)
}
But until setting up the /saves folder you still need to delete all those random files! Where not going to do that with code because you could just manually delete them and than implement that /saves sub file and start deleting them that way... I though I could show you how to delete all the random files with code, it won't be be pretty 😅 (I've done it before you just make a bunch of for loops finding the files by name)
thankkkk!!!!
is this work for WebGL
I dont see why it wouldent 🤷♀️
Tyyy
How i delete a File?
Either find the files on your system or delete your saves directory (file) with code if you even put it in a directory, I dont think we did in this video
If you want an example of using directories watch this video, the save system in it puts all the saves in one main file
Directory example starts at 5:36
ruclips.net/video/Bv-Qie4ISWg/видео.html
Or you can go directly in your system and find it and delete it
On mac: press shift + command + period to show hidden files and go to Library > Application Support > Your games company name and you'll find the saves in there
On windows: I dont have a windows you should probably search this yourself but ill try off the top of my head
In your windows search bar or in files just search "%appdata%" and snoop around in there for your game lol
Hope this helped
@@kapkoder4009i know how to delete a file from the system. I mean, how the player can delete the data ingame? Isn't there a function like, Destroy (File) ;?
@@cake8242 you can make the function
This function will delete a file and recreate it (as a new empty file)
Keep in mind you need this namespace
Which is I think the only one you need for this in particular
using System.IO;
void DeleteSave()
{
string path = Application.persistentDataPath + "/pathKey/";
DirectoryInfo directory = new DirectoryInfo(path);
directory.Delete()
Directory.CreateDirectory(path)
}
@@kapkoder4009 thank you
Hey, any way to make this save a list of Class Object? So I am making a task system and I don't want to make a new file for every task. How do I serialize a list of objects with this method and then load it? Also, I will be rewriting the file with this list of objects. So should I be appending it or just filemode create with my serialized list will overwrite over everything?
Hey! Were you able to figure out how to serialize a list of objects?
Never mind I figured it out
Great Video! I am new to coding and can't seem to save the rotation. Could you provide us with how to add rotation to the save?
Attached are parts of the code I added/modified. Thanks!
Save System:
Quaternion rotation = Quaternion.Euler(data.rotation[0], data.rotation[1], data.rotation[2]);
Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]);
Fish fish = Instantiate(fishPrefab, position, rotation);
Fishdata:
public float[] rotation;
public FishData(Fish fish)
{
Quaternion fishrot = fish.transform.rotation;
rotation = new float[]
{
fishrot.x, fishrot.y, fishrot.z
};
}
Hey, don't use Quaternions or modify they're values individually as they're quite complicated
Instead just save the rotation as a Vector2 or 3 and set the
transform.eulerAngles = savedVectorRotation
Not the transform.rotation, when accessing the objects rotation grab its .eulerAngles, not its .rotation
Example:
float[] rotation;
//you cant save Quaternions or vectors so store the value in a float array
void YourFunction()
{
Vector3 fishRot = fish.transform.eulerAngles
rotation = new float[]
{
fishRot.x, fishRot.y, fishRot.z
}
}
And this is all off the top of my head so don't quote me on it lol
And when loading the rotation just take the saved float array and set the fishes eulerAngles to the elements on that float array you saved
Long story short just use the eulerAngles instead lol
@@kapkoder4009 Thank you Kap Koder! I got it to work!
@@vrgo8279 awesome! Funny thing is I actually ran into the same problem myself a while ago, I was saving and setting the rotation as Quaternion and it would always load wrong, like I save a certain value and it would load a completely different value lol
@@kapkoder4009 I have been trying to save 2 different objects using the same savesystem. Do you know what I would need to change in the scripts in order to save more than one kind of object. Thank you for your help!
@@vrgo8279 well I had to do that...
I had fish and decorations
Decorations needed the position, size and stuff to be saved, basically like a fish
So I made a separate data class (DecorationData.cs)
Have each decoration put themselves into a list of decorations on the SAME SAVESYSTEM.cs (sorry I'm not yelling) so basically, when it was time to save, the save system iterated through all the decorations (just like the fish) saved whatever was needed (see? Like the separate DecorationData.cs class) and loaded them as usual
Long story short, yes you need separate data classes but you need the savesytem to do all the work with the data
If this didn't help maybe you could further elaborate on your dilemma and I could propose a solution because that's what I always do i guess lol
Huh, for me it does not work. I spawn in the fish, and then when I re-open the game after closing it, nothing spawns. Any ideas?
Make sure your adding the fish onto the saves list and make sure your Save game script is spawning the fish it loads on awake
Well, everything should’ve worked idk did you tweak something with the load function? You have to make sure your spawning a prefab and you have a reference to one in the inspector
Wow
The game wants to save and load hundreds of my game objects...
I like the video bro. Very Informative but please dont shoot a video when you're drunk. Peace out
Bro I wasn't drunk
Infactually... I was extremely woke, as if I was Alex Becker
fish :)
:)
...
What a fuckkk ??!
Lol
Does not work
Path Not Found InC:/Users/Dell/AppData/LocalLow/DefaultCompany/Project_Reject/item0
UnityEngine.Debug:LogError(Object)
SaveSystem:LoadItem() (at Assets/Scripts/SaveSystem.cs:61)
SaveSystem:Awake() (at Assets/Scripts/SaveSystem.cs:18)
I've given up on life, same code as you and nothing spawns
Save System code:
public class SaveSystem : MonoBehaviour
{
[Header("Prefabs")]
[SerializeField] Furniture furnitureprefab;
public static List furnitureList = new List();
const string FurniturePath = "/furniture";
const string FurnitureCountPath = "/furniture.count";
public void Awake()
{
LoadFurniture();
}
public void OnApplicationQuit()
{
SaveFurniture();
}
public void SaveFurniture()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + FurniturePath + SceneManager.GetActiveScene().buildIndex;
string countPath = Application.persistentDataPath + FurnitureCountPath + SceneManager.GetActiveScene().buildIndex;
FileStream countStream = new FileStream(countPath, FileMode.Create);
formatter.Serialize(countStream, furnitureList.Count);
countStream.Close();
for (int i = 0; i < furnitureList.Count; i++)
{
FileStream stream = new FileStream(path + i, FileMode.Create);
FurnitureData data = new FurnitureData(furnitureList[i]);
formatter.Serialize(stream, data);
stream.Close();
}
}
public void LoadFurniture()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + FurniturePath + SceneManager.GetActiveScene().buildIndex;
string countPath = Application.persistentDataPath + FurnitureCountPath + SceneManager.GetActiveScene().buildIndex;
int FurnitureCount = 0;
if (File.Exists(countPath))
{
FileStream countStream = new FileStream(countPath, FileMode.Open);
FurnitureCount = (int)formatter.Deserialize(countStream);
countStream.Close();
}
else
{
Debug.LogError("Path not found in " + countPath);
}
for (int i = 0; i < furnitureList.Count; i++)
{
if (File.Exists(path + i))
{
FileStream stream = new FileStream(path + i, FileMode.Open);
FurnitureData data = formatter.Deserialize(stream) as FurnitureData;
stream.Close();
Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]);
Furniture furniture = Instantiate(furnitureprefab, position, Quaternion.identity);
}
else
{
Debug.LogError("Path not found in " + (path + i));
}
}
}
}my "fishdata" - i only want to save position
[Serializable]
public class FurnitureData
{
public float[] position;
public FurnitureData(Furniture furniture)
{
Vector3 furniturePos = furniture.transform.position;
position = new float[]
{
furniturePos.x, furniturePos.y, furniturePos.z
};
}
}
my "fish" class - there's no functionality on this besides adding it to the list because things are handled in other scripts.
public class Furniture : MonoBehaviour
{
public void Awake()
{
SaveSystem.furnitureList.Add(this);
}
}