Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Saving an object to a list from another class.

Discussion in 'Getting Started' started by romanpinkel, Sep 12, 2019.

  1. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    hey everyone.
    I read some posts but they dont help me.
    I have a save-load class with a list of objects:

    Code (CSharp):
    1. public class SaveLoad// : MonoBehaviour I read monobehavior is bad for lists..
    2. {
    3.     public List<GameObject> speicherbareObjekte;
    4.     public void Start()
    5.     {
    6.         speicherbareObjekte = new List<GameObject>();
    7.     }
    8. }
    When I spawn some Objects I want them saved in this lists (from another class)
    Code (CSharp):
    1. void Update()
    2.     {
    3.         if (Input.GetKeyDown(KeyCode.K))
    4.         {
    5.             GameObject go = Instantiate(myPrefab, new Vector3(Random.Range(3.0f, 30.0f), 3, Random.Range(3.0f, 30.0f)), Quaternion.identity);
    6.             SaveLoad.speicherbareObjekte.Add(go); //but this doesnt work
    7.         }
    8.        
    9.     }
    can you please tell me why this doesnt work?
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    When you post a question like this, please always include a description of how it doesn't work. Do you get an error message? What is it? Or is the behavior somehow different from what you wanted, and if so, how?

    In this particular case I can guess that you're getting an error on line 6 of the second script, and it's probably telling you more or less exactly what is wrong: that speicherbareObjekte is not a static property and can only be accessed from an instance.

    So what you're doing here is invalid, but I'm not sure how to advise you because you also haven't told us what you're trying to accomplish. Tell us that, and we can suggest the best approach.
     
  3. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    your guess is correct, I got an error message about the not static property.
    I wanted to add some runtime generated objects into the list from the SaveLoad class.
    Perhaps I have a fix for it but I have to figure out if I can manage to use the SaveLoad for storing object lists (I know it should be possible)
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    You still haven't said what you want to accomplish. So I'll take some guesses.

    If you just need a global list of instantiated GameObjects so several scripts can access them, you can use a public static property in any convenient class. That could be a static class (which is just class that has only static members), or it could be a regular, non-static class. For example, it could even be the MonoBehavior that's responsible for instantiating these things. Just give it a property like:

    Code (csharp):
    1.  
    2.     public static List<GameObject> objects = new List<GameObject>();
    3.  
    ...and then any other code can access it via the name of this class, plus
    .objects
    .

    Or if you want to do it in your SaveLoad class, that's fine too. Just declare the list property static, as shown above. And if you really intend SaveLoad to have nothing but global data and methods like this, then declare it as a
    static class
    rather than just a
    class
    .
     
  5. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    making the list static helped so that I can access it from other classes. Thanks.
    But now I got my next Problem.
    I slighly changed my Save-Load Class so that I can put everything I want to be saved here. According to an example who saved an Int which works properly I now wanna save the List of Objects:


    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using System;
    4. using System.Runtime.Serialization.Formatters.Binary;
    5. using System.IO;
    6.  
    7.  
    8. public class SaveLoad
    9. {
    10.     public static List<GameObject> speicherbareObjekte = new List<GameObject>();  //objects that can be saved
    11.     public static int hops = 0;
    12.  
    13.     public static void Save()
    14.     {
    15.         BinaryFormatter binary = new BinaryFormatter();
    16.         FileStream fStream = File.Create(Application.persistentDataPath + "/Savefile.sav");
    17.  
    18.         SaveManager saver = new SaveManager();
    19.  
    20.         saver.jumps = hops;
    21.         //saver.abgespeicherteObjekte = speicherbareObjekte; //this line causes upon using the problems!
    22.      
    23.         binary.Serialize(fStream, saver);
    24.         fStream.Close();
    25.     }
    26.  
    27.  
    28.     public static void Load()
    29.     {
    30.         if (File.Exists(Application.persistentDataPath + "/Savefile.sav"))
    31.         {
    32.             BinaryFormatter binary = new BinaryFormatter();
    33.             FileStream fStream = File.Open(Application.persistentDataPath + "/Savefile.sav", FileMode.Open);
    34.             SaveManager saver = (SaveManager)binary.Deserialize(fStream);
    35.             fStream.Close();
    36.  
    37.             hops = saver.jumps;
    38.             //speicherbareObjekte = saver.abgespeicherteObjekte;
    39.         }    
    40.     }
    41.  
    42.  
    43.     public static void CountGameObjectsInList()
    44.     {
    45.         int amount = speicherbareObjekte.Count;
    46.         Debug.Log("Elemente in 'speicherbareObjekte' = " + amount);
    47.     }
    48.  
    49.  
    50.     public static void AddGameObjectToList(GameObject go)
    51.     {
    52.         speicherbareObjekte.Add(go);
    53.     }
    54. }
    55.  
    56.  
    57. [Serializable]
    58. class SaveManager
    59. {
    60.     public int jumps;
    61.     public List<GameObject> abgespeicherteObjekte;  //alreadySavedObjects
    62. }
    63.  
    this allows me to add and count the Objects with given methods and I can save and load the Integers for jumping/hopping.
    But if I activate the commented lines in Save and use it I get this error message:

    SerializationException: Type 'UnityEngine.GameObject' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
    System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (System.RuntimeType type) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.FormatterServices+<>c__DisplayClass9_0.<GetSerializableMembers>b__0 (System.Runtime.Serialization.MemberHolder _) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.FormatterServices.GetSerializableMembers (System.Type type, System.Runtime.Serialization.StreamingContext context) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo () (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize (System.Type objectType, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.SerializationBinder binder) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize (System.Type objectType, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.SerializationBinder binder) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteArray (System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo objectInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo memberNameInfo, System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo memberObjectInfo) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write (System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo objectInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo memberNameInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo typeNameInfo) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize (System.Object graph, System.Runtime.Remoting.Messaging.Header[] inHeaders, System.Runtime.Serialization.Formatters.Binary.__BinaryWriter serWriter, System.Boolean fCheck) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers, System.Boolean fCheck) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) (at <1f0c1ef1ad524c38bbc5536809c46b48>:0)
    SaveLoad.Save () (at Assets/Scripts/Roman/SaveLoad.cs:36)
    Menu_Pause.Speichern () (at Assets/Scripts/Roman/Menu_Pause.cs:50)
    UnityEngine.Events.InvokableCall.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent/UnityEvent.cs:166)
    UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent/UnityEvent/UnityEvent_0.cs:58)
    UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:66)
    UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:108)
    UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:50)
    UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:261)
    UnityEngine.EventSystems.EventSystem:Update()

    whats so different about saving the object(-lists)?
     
    Last edited: Sep 13, 2019
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    Objects (much less lists of objects) can't typically be serialized (converted into bytes that can be written to a file).

    What is it you are trying to do? Don't say "I'm trying to save objects to a file." We can see that. Answer at a higher level. Why are you trying to save objects to a file?
     
  7. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    Before I answer, I googled and worked on saving 1 special object with all its data like position, Eulerangles and scale.
    This works now. (as string to json)

    The main goal is to create objects during runtime, position them on a map and save all their positions, angles and scales so I can continue working another time.
    I thought a list would be the easiest way to store all those objects instead of numbering them.
    When I iterate throught the list I want to save all those objects.
     
    Last edited: Sep 13, 2019
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    That's a pretty advanced project for a beginner. I would generally advise you to start with a few simple games, like a Flappy Bird or Doodle Jump clone.

    But to do what you want, as you discovered, you need to convert all the data necessary to recreate your scene in some format like JSON. And then when you reload the scene, read and parse that data, and recreate the objects.
     
  9. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    As we say: "you grow in your challenges".
    I'll try iterating the list tomorror and report back if it worked or where the hopefully not existing problems are.
     
  10. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    777
    Off-topic, but where did you read this?
    There is no correlation between using a List in a class that inherits or doesn't inherit MonoBehaviour.
     
    Joe-Censored and JoeStrout like this.
  11. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    @Vyrken: Sorry I cant remember where i read it or if it was mentioned in a YT-Tutorial.

    With a friends help, I could also manage to finally save several objects to 1 json file.

    Now theres just 1 small Problem left...

    the class contains
    Code (CSharp):
    1. public GameObject myPrefab;
    which is later called when beeing loaded.

    Code (CSharp):
    1.  Instantiate(myPrefab, new Vector3(sgoe.pos_x, sgoe.pos_y, sgoe.pos_z), Quaternion.identity);
    this gives me a new objects from this prefab which I have to drag and drop in the editor manually onto myPrefab.

    is there a way to use an prefab from the folder /assets/objects/ calles wall01.obj directly without a prefab?

    thanks in advance.
     
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    No. You can do it if your prefab is in the Resources folder, using Resources.Load. Or, you can put a big switch statement in your code that maps prefab names (from your JSON file) to the corresponding prefab property on the script.
     
  13. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    20
    seems to work :)

    thanks a lot!

    [Solved]