SAVE & LOAD MULTIPLE OBJECTS In Unity (With tips and debugging at end!)

Поділитися
Вставка
  • Опубліковано 25 лис 2020
  • In depth Save and Load Multiple Objects tutorial! with tips and debugging help at the end, saved as binary
    Inspired by Brackeys Save System tutorial but optimised to save multiple objects, also a look at what happened in his comment section
    Copying code in not just cut and dry
    · You need a "SaveSystem" gameObject with the "SaveSystem.cs" on it
    · The "SaveSystem" gameObject needs a reference to your objectPrefab
    · Your objects script needs an OnDestroy() callback to remove itself from the saves list (optional)
    · Your objects script needs an Awake() callback to add itself to the saves list
    · If your saving with android then Save with "OnApplicationPause()"
    FishData.cs class BELOW
    using UnityEngine;
    [System.Serializable]
    public class FishData
    {
    //Replace these example variable with your objects variables
    //that you wish to save
    public int health;
    public string name;
    public float[] position;
    public FishData(Fish fish)
    {
    health = fish.health;
    name = fish.name;
    Vector3 fishPos = fish.transform.position;
    position = new float[]
    {
    fishPos.x, fishPos.y, fishPos.z
    };
    }
    }
    SaveSystem.cs class BELOW
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    using UnityEngine.SceneManagement;
    public class SaveSystem : MonoBehaviour
    {
    [Header("Prefabs")]
    [SerializeField] Fish fishPrefab;
    //Angled brackets not allowed in desc, replace the
    //parenthesis in (Fish) with angled brackets
    public static List(Fish) fishes = new List(Fish)();
    //Rename your strings according to what your saving
    const string FISH_SUB = "/fish";
    const string FISH_COUNT_SUB = "/fish.count";
    void Awake()
    {
    LoadFish();
    }
    //Use if Android
    //void OnApplicationPause(bool pause)
    //{
    // SaveFish();
    //}
    void OnApplicationQuit()
    {
    SaveFish();
    }
    void SaveFish()
    {
    BinaryFormatter formatter = new BinaryFormatter();
    string path = Application.persistentDataPath + FISH_SUB + SceneManager.GetActiveScene().buildIndex;
    string countPath = Application.persistentDataPath + FISH_COUNT_SUB + SceneManager.GetActiveScene().buildIndex;
    FileStream countStream = new FileStream(countPath, FileMode.Create);
    formatter.Serialize(countStream, fishes.Count);
    countStream.Close();
    //Replace "lessThan" with a left angled bracket
    for (int i = 0; i lessThan fishes.Count; i++)
    {
    FileStream stream = new FileStream(path + i, FileMode.Create);
    FishData data = new FishData(fishes[i]);
    formatter.Serialize(stream, data);
    stream.Close();
    }
    }
    void LoadFish()
    {
    BinaryFormatter formatter = new BinaryFormatter();
    string path = Application.persistentDataPath + FISH_SUB + SceneManager.GetActiveScene().buildIndex;
    string countPath = Application.persistentDataPath + FISH_COUNT_SUB + SceneManager.GetActiveScene().buildIndex;
    int fishCount = 0;
    if (File.Exists(countPath))
    {
    FileStream countStream = new FileStream(countPath, FileMode.Open);
    fishCount = (int)formatter.Deserialize(countStream);
    countStream.Close();
    }
    else
    {
    Debug.LogError("Path not found in " + countPath);
    }
    //Replace "lessThan" with an left angled bracket
    for (int i = 0; i lessThan fishCount; i++)
    {
    if (File.Exists(path + i))
    {
    FileStream stream = new FileStream(path + i, FileMode.Open);
    FishData data = formatter.Deserialize(stream) as FishData;
    stream.Close();
    Vector3 position = new Vector3(data.position[0], data.position[1], data.position[2]);
    Fish fish = Instantiate(fishPrefab, position, Quaternion.identity);
    fish.health = data.health;
    fish.name = data.name;
    }
    else
    {
    Debug.LogError("Path not found in " + (path + i));
    }
    }
    }
    }

КОМЕНТАРІ • 135

  • @theAdventureLine
    @theAdventureLine Місяць тому +2

    I know its been 3 years, but bro casually saved my bachelors thesis, bless you

  • @Jimmlad
    @Jimmlad 2 роки тому +3

    Thank you for deciding to take the time to make this highly specific tutorial. This is exactly what I needed :)

  • @garrettdeveloper
    @garrettdeveloper 3 роки тому +8

    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!

    • @kapkoder4009
      @kapkoder4009  3 роки тому +1

      I'm happy this came to your help! 😊

  • @willmaddison12364
    @willmaddison12364 3 роки тому +8

    You know its a good day when kap koder uploads

  • @Robocat754
    @Robocat754 Рік тому

    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!

  • @furkanbilici4615
    @furkanbilici4615 2 роки тому +1

    Really a very successful tutorial was clear and understandable thank you very much...

  • @headrushgaming2614
    @headrushgaming2614 Рік тому

    this ... saved me. you actually have no idea! thankyou!

  • @stevewade4544
    @stevewade4544 Рік тому +1

    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)

    • @kapkoder4009
      @kapkoder4009  Рік тому +1

      I actually haven’t coded in a while… what happened? Was it exploited or considered unsafe now?

    • @rashidfarhan6223
      @rashidfarhan6223 Рік тому

      @@kapkoder4009 yes

  • @boedemirkol8857
    @boedemirkol8857 2 роки тому

    Bro you saved my life... Thanks a lot!

  • @izabellak9523
    @izabellak9523 3 роки тому

    Nice videos keep it going!

  • @uber6604
    @uber6604 2 роки тому +3

    i think i found a perfect tutorial for my use
    ill see in some time

  • @uber6604
    @uber6604 2 роки тому

    It worked! thanks

  • @shadowgodthegamer5738
    @shadowgodthegamer5738 2 роки тому

    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

  • @neozoid7009
    @neozoid7009 2 роки тому

    Awesome 👍👍

  • @hasanalkan8624
    @hasanalkan8624 Рік тому

    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?

  • @3bomb
    @3bomb 5 місяців тому

    Thanks for this, it was handy. I lol'd at the Joe Rogan bit.

  • @samirisgood5735
    @samirisgood5735 Рік тому

    Thank You!

  • @foreign-livingtheamericand8782
    @foreign-livingtheamericand8782 2 роки тому

    wow, love this video. will try to save the binary to mysql tho😟

  • @aser28860d
    @aser28860d 8 днів тому

    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 !!

  • @channeltrash6257
    @channeltrash6257 2 роки тому

    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)

  • @frunk7671
    @frunk7671 Рік тому

    You are the best

  • @ProgrammingEditingHub
    @ProgrammingEditingHub 2 роки тому

    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

  • @kainushia1073
    @kainushia1073 Рік тому

    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

  • @HasbiHB
    @HasbiHB 2 роки тому

    thankkkk!!!!

  • @shankarshivam1877
    @shankarshivam1877 2 роки тому +1

    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 .

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      Is the new objects your spawning adding itself to the saves list?

  • @barttv7067
    @barttv7067 Рік тому

    Tyyy

  • @Alliance.AutoCare
    @Alliance.AutoCare 3 роки тому +1

    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??

    • @kapkoder4009
      @kapkoder4009  3 роки тому

      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?

  • @KitchenTableMaths
    @KitchenTableMaths 2 роки тому

    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

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      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

    • @KitchenTableMaths
      @KitchenTableMaths 2 роки тому

      @@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.

    • @Robocat754
      @Robocat754 Рік тому

      @@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.

  • @yannikn2253
    @yannikn2253 3 роки тому

    For me it only loads one fish and not all... what is the problem???

  • @VelikoStudio
    @VelikoStudio Рік тому

    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
      @kapkoder4009  Рік тому +1

      Make sure that the objects your saving has a function to remove itself from the saves list in the OnDestroy() callback function

    • @VelikoStudio
      @VelikoStudio Рік тому

      @@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 :)

  • @hoaxygen
    @hoaxygen 8 місяців тому

    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.

  • @ghostghostgaming5637
    @ghostghostgaming5637 2 роки тому

    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?

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      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

    • @ghostghostgaming5637
      @ghostghostgaming5637 2 роки тому

      @@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?

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      @@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

    • @ghostghostgaming5637
      @ghostghostgaming5637 2 роки тому

      @@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.

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      @@ghostghostgaming5637 huh interesting
      It could have been that you didn't restart the game after you saved your script?

  • @trimurdev
    @trimurdev 2 роки тому

    When i try to spawn something with a data script it says 'blockdata' is missing the class attribute 'ExtensionOfNativeClass'! and The class named 'blockdata' is not derived from MonoBehaviour or ScriptableObject!. Idk what to do.

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      Make sure you don't forget to add [System.Serializable]
      On top of the class your saving

    • @trimurdev
      @trimurdev 2 роки тому

      @@kapkoder4009 i did

  • @donnewcomb3547
    @donnewcomb3547 2 роки тому

    Okay so, how do you load a fish that has been destroyed?

  • @no.91928
    @no.91928 Рік тому

    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?

    • @kapkoder4009
      @kapkoder4009  Рік тому

      You can search for the files string name (full path and name you attached to the path) and delete it, pretty straightforward

    • @no.91928
      @no.91928 Рік тому

      @@kapkoder4009 how would this look like implemented in code?

  • @TheXdestruidor
    @TheXdestruidor 3 роки тому

    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?

    • @kapkoder4009
      @kapkoder4009  3 роки тому

      You can watch this video:
      ua-cam.com/video/Bv-Qie4ISWg/v-deo.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

    • @TheXdestruidor
      @TheXdestruidor 3 роки тому +1

      @@kapkoder4009 very thanks man i gonna jump into this tutorial

  • @alexyoung2795
    @alexyoung2795 Рік тому

    Never mind I figured it out

  • @SonuKumar-js5wv
    @SonuKumar-js5wv 2 роки тому

    i want to save my shop system how to ? help me!

  • @Lajlaj
    @Lajlaj 2 роки тому

    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)

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      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

    • @Lajlaj
      @Lajlaj 2 роки тому

      @@kapkoder4009 Very much appreciated :)

    • @ThatRazzy
      @ThatRazzy 2 роки тому

      Hey, any solution for this?

    • @3bomb
      @3bomb 5 місяців тому

      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.

    • @Lajlaj
      @Lajlaj 5 місяців тому +1

      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

  • @neozoid7009
    @neozoid7009 2 роки тому

    How can i implement this method for objects instantiated in different class. Because I already have a class for instantiation. Please help😭

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      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

  • @eliotgruslin7068
    @eliotgruslin7068 3 роки тому

    How can I use this system with differents kind of fish ?

    • @kapkoder4009
      @kapkoder4009  3 роки тому +1

      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

  • @Driverbazona
    @Driverbazona 2 роки тому

    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.

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      I think you need to remove the fish from the saves list when you destroy it

    • @Driverbazona
      @Driverbazona 2 роки тому

      Yep, thanks that was it :)

  • @Driverbazona
    @Driverbazona 2 роки тому

    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.

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      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

    • @Driverbazona
      @Driverbazona 2 роки тому

      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😊

  • @DuszpasteX
    @DuszpasteX 3 роки тому

    Wow

  • @Driverbazona
    @Driverbazona 2 роки тому

    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 :)

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      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?

    • @Driverbazona
      @Driverbazona 2 роки тому

      @@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
      @kapkoder4009  2 роки тому

      @@Driverbazona send me your code

    • @Driverbazona
      @Driverbazona 2 роки тому

      @@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);
      }
      }
      }

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      @@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!

  • @brunosoares6717
    @brunosoares6717 2 роки тому

    mine works perfectly in editor but when i make an android build it doesnt work, anyone know what should be?

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      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

  • @vrgo8279
    @vrgo8279 2 роки тому

    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
    };
    }

    • @kapkoder4009
      @kapkoder4009  2 роки тому +2

      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
      @vrgo8279 2 роки тому

      @@kapkoder4009 Thank you Kap Koder! I got it to work!

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      @@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

    • @vrgo8279
      @vrgo8279 2 роки тому

      @@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!

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      @@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

  • @ForIEqualsZero
    @ForIEqualsZero Рік тому

    it might be obvious but I'm really bad at unity so how can I save multiple objects with this script?

    • @AzzeddineXT
      @AzzeddineXT Рік тому

      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!

    • @Golden_Hephaestus
      @Golden_Hephaestus Рік тому

      @@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.

  • @Driverbazona
    @Driverbazona 2 роки тому

    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 :)

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      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

    • @Driverbazona
      @Driverbazona 2 роки тому

      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.

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      @@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
      ua-cam.com/video/Bv-Qie4ISWg/v-deo.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)

  • @NathoSteveo
    @NathoSteveo 3 роки тому +1

    fish :)

  • @anumey1
    @anumey1 Рік тому

    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?

    • @Golden_Hephaestus
      @Golden_Hephaestus Рік тому

      Hey! Were you able to figure out how to serialize a list of objects?

  • @bhanukadasanayaka3457
    @bhanukadasanayaka3457 2 роки тому +1

    is this work for WebGL

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      I dont see why it wouldent 🤷‍♀️

  • @cake8242
    @cake8242 3 роки тому +1

    How i delete a File?

    • @kapkoder4009
      @kapkoder4009  3 роки тому

      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
      ua-cam.com/video/Bv-Qie4ISWg/v-deo.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

    • @cake8242
      @cake8242 3 роки тому

      ​@@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) ;?

    • @kapkoder4009
      @kapkoder4009  3 роки тому +1

      @@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)
      }

    • @cake8242
      @cake8242 3 роки тому

      @@kapkoder4009 thank you

  • @alexyoung2795
    @alexyoung2795 Рік тому

    The game wants to save and load hundreds of my game objects...

  • @agapi8731
    @agapi8731 2 роки тому

    I like the video bro. Very Informative but please dont shoot a video when you're drunk. Peace out

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      Bro I wasn't drunk

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      Infactually... I was extremely woke, as if I was Alex Becker

  • @babasheep2828
    @babasheep2828 2 роки тому

    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?

    • @kapkoder4009
      @kapkoder4009  2 роки тому +1

      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

    • @kapkoder4009
      @kapkoder4009  2 роки тому

      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

  • @kapitolroblox_pro_forever2060
    @kapitolroblox_pro_forever2060 3 роки тому

    ...

  • @kapitolroblox_pro_forever2060
    @kapitolroblox_pro_forever2060 3 роки тому

    Lol

  • @gooty6185
    @gooty6185 2 роки тому

    What a fuckkk ??!

  • @F_U
    @F_U Рік тому +1

    This tutorial is worth watching to learn some things or get some ideas, but not for how to do a save system. BinaryFormatter is dangerous and should not be used: learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

  • @olexanderbatishchev1161
    @olexanderbatishchev1161 Рік тому

    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)

  • @jacineyatrakos3149
    @jacineyatrakos3149 2 роки тому +1

    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);
    }
    }