Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Dynamic Save/Load (Advanced)..Need Help

Discussion in 'Scripting' started by sentar, Sep 17, 2019.

  1. sentar

    sentar

    Joined:
    Feb 27, 2017
    Posts:
    44
    After banging my head against the wall for quite a while I'm at the point where I need help. I'm stuck at the point where I'm thinking my Lists are not ideal for organizing my prefabs in my scene. As I'm currently getting to the end of my Alpha build I know having a dynamic save/load setup is most ideal especially for patch management for releasing beta/production builds to the public without having them to delete their saves.

    The two problems I'm experiencing: *Save & Load Functions*

    ** The save function I do not know how to structure it better to organize a more comprehensive list of prefabs to indicate their name, position, rotation accurately. Accurately meaning which line in the lists belongs more to the name that dictates position/rotation so certain prefabs don't get the wrong position/rotation of another saved prefab (this starts to become more of a problem if certain prefabs are destroyed during run-time then saving afterwards that creates a new line which each list may not match correctly). **

    ** The load function more accurately structure the data to load accurately from the saved function, and make sure the instantiation process is successful if a prefab is not loaded in yet. I've been getting errors where the certain prefab is null, and I'm wondering if I need to have my entire prefab build items into the Resource folder **

    For everyone that is an expert coder with 5+ experience in Game Dev work I commend you, and I request for my understanding to get more broad so I can become skilled like you. Have a great day/evening Game Dev Guru's!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using System.IO;
    6. using System.Runtime.Serialization.Formatters.Binary;
    7. using UnityEngine.SceneManagement;
    8.  
    9. public class Database : MonoBehaviour
    10. {
    11.  
    12.     public bool loaded_game;
    13.     public GameObject[] scene;
    14.     public List<GameObject> scene_objects;
    15.     string Save_File = "/SaveGame";
    16.     string File_Ext = ".bin";
    17.  
    18.     public List<string> scence_string;
    19.     public List<string> save_vectors_position;
    20.     public List<string> save_object_rotation;
    21.  
    22.     [SerializeField]
    23.     private List<Vector3> object_vectors;
    24.     [SerializeField]
    25.     private List<Quaternion> object_rotations;
    26.  
    27.     public List<string> load_scene_names;
    28.     public List<string> load_vectors_position;
    29.     public List<string> load_vectors_rotation;
    30.     public List<Vector3> place_positions_byvector;
    31.     public List<Vector3> place_object_rotation_byvector;
    32.     private Stream stream;
    33.  
    34.     private void Awake()
    35.     {
    36.         scene_object_list();
    37.     }
    38.  
    39.     public void scene_object_list()
    40.     {
    41.  
    42.         scene = GameObject.FindObjectsOfType<GameObject>();
    43.        
    44.         if (scene.Length > 0)
    45.         {
    46.  
    47.             transformtovector3();
    48.             transformtorotation();
    49.         }
    50.     }
    51.  
    52.     public void transformtovector3()
    53.     {
    54.         if (scene.Length != object_vectors.Count)
    55.         {
    56.             object_vectors.Clear();
    57.             foreach (GameObject vectors in scene)
    58.             {
    59.                 object_vectors.Add(vectors.transform.localPosition);
    60.             }
    61.         }
    62.     }
    63.  
    64.     public void transformtorotation()
    65.     {
    66.         if (scene.Length != object_rotations.Count)
    67.         {
    68.             object_rotations.Clear();
    69.             foreach (GameObject vectors in scene)
    70.             {
    71.                 object_rotations.Add(vectors.transform.localRotation);
    72.             }
    73.         }
    74.     }
    75.  
    76.     public void save()
    77.     {
    78.         scene_object_list();
    79.  
    80.         if (File.Exists(Application.persistentDataPath + Save_File + File_Ext))
    81.         {
    82.             File.Delete(Application.persistentDataPath + Save_File + File_Ext);
    83.         }
    84.  
    85.         Stream stream = File.Open(Application.persistentDataPath + Save_File + File_Ext, FileMode.CreateNew);
    86.         BinaryFormatter bf = new BinaryFormatter();
    87.  
    88.         foreach (GameObject getname in scene)
    89.         {
    90.             scence_string.Add(getname.gameObject.name);
    91.             save_vectors_position.Add(getname.gameObject.transform.position.ToString());
    92.             save_object_rotation.Add(getname.gameObject.transform.localEulerAngles.ToString());
    93.         }
    94.        
    95.         //object names
    96.         bf.Serialize(stream, scence_string);
    97.  
    98.         //object vector3 position
    99.         bf.Serialize(stream, save_vectors_position);
    100.  
    101.         //object rotation
    102.         bf.Serialize(stream, save_object_rotation);
    103.  
    104.         //end of saving function
    105.         stream.Close();
    106.     }
    107.  
    108.     public void load()
    109.     {
    110.         if (loaded_game == false)
    111.         {
    112.             //find any gameobjects in the scene
    113.             scene = GameObject.FindObjectsOfType<GameObject>();
    114.  
    115.             //// Do I delete everything in my scene then re-instantiate prefabs or is there a better way//////
    116.        
    117.             //If any strings are available remove them in a running state game//
    118.             scene_objects.Clear();
    119.             load_vectors_rotation.Clear();
    120.             place_object_rotation_byvector.Clear();
    121.             load_scene_names.Clear();
    122.             load_vectors_position.Clear();
    123.             ////
    124.  
    125.             //start the loading process//
    126.             Stream stream = File.Open(Application.persistentDataPath + Save_File + File_Ext, FileMode.Open);
    127.             BinaryFormatter bf = new BinaryFormatter();
    128.  
    129.            
    130.             load_scene_names = (List<string>)bf.Deserialize(stream);
    131.             load_vectors_position = (List<string>)bf.Deserialize(stream);
    132.             load_vectors_rotation = (List<string>)bf.Deserialize(stream);
    133.             stream.Close();
    134.  
    135.             scene_object_list();
    136.  
    137.             //If gameobjects are in scene still
    138.             foreach (GameObject prescene in scene)
    139.             {
    140.                 scene_objects.Add(prescene);
    141.             }
    142.             ////
    143.  
    144.             //load gameobjects from text file
    145.             if (load_scene_names != null)
    146.             {
    147.                 for (int i = 0; i < load_scene_names.Count; i++)
    148.                 {
    149.            
    150.                     if (scene_objects[i].name != load_scene_names[i] && (scene_objects[i].name != "GameRunner"))
    151.                     {
    152.                        
    153.                         var a = Instantiate(Resources.Load("/Saves" + load_scene_names[i]) as GameObject);
    154.                         if (a != null)
    155.                         {
    156.                             a.name = load_scene_names[i];
    157.                             scene_objects.Add(a);
    158.                         }
    159.                     }
    160.                 }
    161.                
    162.                
    163.                 if (load_scene_names.Count > scene.Length)
    164.                 {
    165.                     scene_object_list();
    166.                 }
    167.             } //end of load_scene_names
    168.  
    169.             if (load_vectors_position.Count > 0)
    170.             {
    171.                 foreach (GameObject prescene in scene)
    172.                 {
    173.                     scene_objects.Add(prescene);
    174.                 }
    175.  
    176.                 foreach (string positioning in load_vectors_position)
    177.                 {
    178.                     string[] temp = positioning.Substring(1, positioning.Length - 2).Split(',');
    179.                     float x = float.Parse(temp[0]);
    180.                     float y = float.Parse(temp[1]);
    181.                     float z = float.Parse(temp[2]);
    182.                     Vector3 rValue = new Vector3(x, y, z);
    183.  
    184.                     place_positions_byvector.Add(rValue);
    185.                 }
    186.  
    187.                 if (place_positions_byvector.Count > 0)
    188.                 {
    189.  
    190.                     for (int i = 0; i < place_positions_byvector.Count; i++)
    191.                     {
    192.                         if (scene_objects[i].name != "Text")
    193.                         {
    194.                             scene_objects[i].transform.InverseTransformPoint(place_positions_byvector[i]);
    195.                         }
    196.                     }
    197.  
    198.                 }
    199.             }
    200.  
    201.             if (load_vectors_rotation.Count > 0)
    202.             {
    203.                 place_object_rotation_byvector.Clear();
    204.                 if (place_object_rotation_byvector.Count < scence_string.Count)
    205.                 {
    206.                     foreach (string positioning in load_vectors_rotation)
    207.                     {
    208.  
    209.                         string[] temp = positioning.Substring(1, positioning.Length - 2).Split(',');
    210.                         float x = float.Parse(temp[0]);
    211.                         float y = float.Parse(temp[1]);
    212.                         float z = float.Parse(temp[2]);
    213.  
    214.                         Vector3 rotValue = new Vector3(x, y, z);
    215.  
    216.                         place_object_rotation_byvector.Add(rotValue);
    217.                     }
    218.  
    219.                     if (place_object_rotation_byvector.Count > 0)
    220.                     {
    221.  
    222.                         for (int i = 0; i < scene_objects.Count; i++)
    223.                         {
    224.                             if (scene_objects[i].name != "Text")
    225.                             {
    226.  
    227.                                 scene_objects[i].transform.localEulerAngles = place_object_rotation_byvector[i];
    228.                             }
    229.                         }
    230.  
    231.                     }
    232.                 }
    233.             }
    234.             loaded_game = true;
    235.         }
    236.     }
    237. }
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Use scriptable objects for game metadata. You can have an asset with a list you want and do not care how it is saved | loaded
     
  3. sentar

    sentar

    Joined:
    Feb 27, 2017
    Posts:
    44
    Hi Palex-nx,

    Thank you for your reply, are you saying to load the scene with nothing but the scriptableobject whenever the player attempts to load their saved game to help build everything out correctly? If so, what would be the reason to do ScriptableObjects (besides memory usage) over instancing Prefabs from a resource folder?