Search Unity

Question Help please, Saving system giving me a confusing error

Discussion in 'Scripting' started by CodeMateo, Aug 12, 2020.

  1. CodeMateo

    CodeMateo

    Joined:
    May 21, 2020
    Posts:
    77
    Error:
    Code (CSharp):
    1. SerializationException: Type 'UnityEngine.Transform' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
    2. System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (System.RuntimeType type) (at <437ba245d8404784b9fbab9b439ac908>:0)
    3. System.Runtime.Serialization.FormatterServices+<>c__DisplayClass9_0.<GetSerializableMembers>b__0 (System.Runtime.Serialization.MemberHolder _) (at <437ba245d8404784b9fbab9b439ac908>:0)
    4. System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) (at <437ba245d8404784b9fbab9b439ac908>:0)
    5. System.Runtime.Serialization.FormatterServices.GetSerializableMembers (System.Type type, System.Runtime.Serialization.StreamingContext context) (at <437ba245d8404784b9fbab9b439ac908>:0)
    6. System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo () (at <437ba245d8404784b9fbab9b439ac908>:0)
    7. 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 <437ba245d8404784b9fbab9b439ac908>:0)
    8. 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 <437ba245d8404784b9fbab9b439ac908>:0)
    9. 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 <437ba245d8404784b9fbab9b439ac908>:0)
    10. 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 <437ba245d8404784b9fbab9b439ac908>:0)
    11. 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 <437ba245d8404784b9fbab9b439ac908>:0)
    12. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers, System.Boolean fCheck) (at <437ba245d8404784b9fbab9b439ac908>:0)
    13. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers) (at <437ba245d8404784b9fbab9b439ac908>:0)
    14. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) (at <437ba245d8404784b9fbab9b439ac908>:0)
    15. SaveSystem.SaveScene (SceneData sceneData) (at Assets/Code/SaveSystem.cs:15)
    16. SceneData.SaveScene () (at Assets/Code/SceneData.cs:31)
    17. NextScene+<LoadLevel>d__7.MoveNext () (at Assets/Code/NextScene.cs:44)
    18. UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <23a7799da2e941b88c6db790c607d655>:0)
    19.  
    SceneData:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SceneData : MonoBehaviour
    6. {
    7.     public List<Transform> rooms;
    8.     public List<Transform> loot;
    9.     public List<Transform> enemy;
    10.  
    11.     public void GameData()
    12.     {
    13.         foreach (GameObject r in GameObject.FindGameObjectsWithTag("Rooms"))
    14.         {
    15.             rooms.Add(r.GetComponent<Transform>());
    16.         }
    17.  
    18.         foreach (GameObject l in GameObject.FindGameObjectsWithTag("Loot"))
    19.         {
    20.             loot.Add(l.GetComponent<Transform>());
    21.         }
    22.  
    23.         foreach (GameObject e in GameObject.FindGameObjectsWithTag("Enemy"))
    24.         {
    25.             enemy.Add(e.GetComponent<Transform>());
    26.         }
    27.     }
    28.  
    29.     public void SaveScene()
    30.     {
    31.         SaveSystem.SaveScene(this);
    32.     }
    33.  
    34.     public void LoadScene()
    35.     {
    36.         GameData();
    37.  
    38.         GameData data = SaveSystem.LoadScene();
    39.  
    40.         rooms = data.rooms;
    41.         loot = data.loot;
    42.         enemy = data.enemy;
    43.     }
    44. }
    GameData:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [System.Serializable]
    6. public class GameData
    7. {
    8.     public List<Transform> rooms;
    9.     public List<Transform> loot;
    10.     public List<Transform> enemy;
    11.  
    12.     public GameData (SceneData sceneData)
    13.     {
    14.         rooms = sceneData.rooms;
    15.  
    16.         loot = sceneData.loot;
    17.  
    18.         enemy = sceneData.enemy;
    19.     }
    20. }
    SaveSystem:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.IO;
    3. using System.Runtime.Serialization.Formatters.Binary;
    4.  
    5. public static class SaveSystem
    6. {
    7.     public static void SaveScene (SceneData sceneData)
    8.     {
    9.         BinaryFormatter formatter = new BinaryFormatter();
    10.         string path = Path.Combine(Application.persistentDataPath, "scene.Alden");
    11.         FileStream stream = new FileStream(path, FileMode.Create);
    12.  
    13.         GameData data = new GameData(sceneData);
    14.  
    15.         formatter.Serialize(stream, data);
    16.         stream.Close();
    17.     }
    18.  
    19.     public static GameData LoadScene()
    20.     {
    21.         string path = Path.Combine(Application.persistentDataPath, "scene.Alden");
    22.         if (File.Exists(path))
    23.         {
    24.             BinaryFormatter formatter = new BinaryFormatter();
    25.             FileStream stream = new FileStream(path, FileMode.Open);
    26.  
    27.             GameData data = formatter.Deserialize(stream) as GameData;
    28.             stream.Close();
    29.  
    30.             return data;
    31.         }
    32.         else
    33.         {
    34.             UnityEngine.Debug.Log("Save file not found in" + path);
    35.             return null;
    36.         }
    37.     }
    38. }
    39.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
  3. CodeMateo

    CodeMateo

    Joined:
    May 21, 2020
    Posts:
    77
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    [System.Serializable] is an attribute used to indicate that it's safe to serialize a class. (NOTE: This is an older system, more recent serialization schemes may not use this attribute.) You're trying to serialize a class that isn't decorated with that attribute, and the serializer is complaining that it's only allowed to serialize classes with that attribute.
     
  5. CodeMateo

    CodeMateo

    Joined:
    May 21, 2020
    Posts:
    77
    Ok that makes a bit more sense, how would be the best way to fix this, by putting something in front of public List...?
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    The best way to fix this is to stop trying to save Transforms.

    If you were trying to save your own custom class, and there was no reason that it shouldn't be safe to serialize, then you would add the [System.Serializable] attribute in front of the class definition. (Like you already did with the GameData class.)

    In this case, the class that is giving you trouble is Transform. You can't add attributes to the Transform class without recompiling UnityEngine, because it's not your class and the source code that defines it isn't in your project.

    Even if you could add the attribute, that might have weird side-effects in other areas that would be hard to predict, because Transform is used in tons of other code that was written on the assumption that Transform is defined in the way that Transform is currently defined, and if you mess with that definition then that code might fail in subtle ways.

    And saving the Transform probably isn't really what you wanted to do in the first place, because I bet lists named things like "loot" and "enemies" contain data that you care about that isn't actually part of the Transform class.


    So what you ought to do is to make a list of what information you actually care about and need to save, and put just that information into a safely-serializable data structure, and serialize that instead.
     
    Kurt-Dekker likes this.
  7. CodeMateo

    CodeMateo

    Joined:
    May 21, 2020
    Posts:
    77
    Ok cool so there’s no way to do it with game objects instead of transforms
     
  8. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Wholesale saving of game objects is not directly supported and in many cases, even if you could do it, you would have performance problems. My recommendation is to save only the fields that you really need.
     
  9. CodeMateo

    CodeMateo

    Joined:
    May 21, 2020
    Posts:
    77
    Dang alright, thank you for all the help