Saving List<T>'s in PlayerPrefs?

So I know how to go about saving strings, ints, and even enums in the PlayerPrefs; but how would I save a List? (I’m not asking how to save an Array, so please don’t give information on that.) Also, the List's are lists of GameObjects.

You can’t save gameobjects to playerprefs
You’ll have to store the values of properties that you need as floats and strings, and then rebuild the GO when you load, and/or relying on prefabs to go part way

Note, because a List can be turned into an array, information on that would be helpful. You’d just have an extra step when reading and writing the array. When writing you’d call ‘ToArray’ on the list, and when reading you’d clear the list and AddRange the array.

As for the type you want to save is a GameObject. No, you can’t save that to playerprefs. You can only save things that can be easily represented as either a string/number/bool. So if you can serialize the object so that it can be stored as one of those, you’re good. A GameObject can not be serialized that easily.

Alright. So I made an adjustment. What I’m doing now is making a List of “BaseEnemy” classes. The BaseEnemy class is a series of strings, int, and bools. What would be the easiest way to save this List to the PlayerPrefs?

Hello.

If I have to do that with playerpref, I will create several keys like this :

PlayerPref.SetInt(“EnemyX:IntValue”, intvalue);

And save these keys somewhere in a file.

The most difficult in that case is you will have a lot of keys.

I work on several maner to save data for a personal project.

I suggest you to use the BinaryFormatter (BinaryFormatter.Serialize Method (System.Runtime.Serialization.Formatters.Binary) | Microsoft Learn good exemple of how to save/load data)

or ScriptableObject from Unity, but perhaps it’s too extrem to save a list.

Gameobject cannot be saved as “GameObject” (even if you use ScriptableObject if I don’t make a mistake). You have to “cut” it (stock position, rotation and name in other variables).

Hope I help you !

@Katasa_1 was your answer a way to save List or List (where BaseEnemy is a class)?

Oups, sorry !

It’s to save List :slight_smile:

Serialise your list to JSON, then write it out as a string to player prefs. There is a limit to playerprefs string length, so you may need to check that out for your platform. JSON.net is the one I use personally.

Or just skip player prefs and searilze your data out to XML or json in a file.

1 Like

Alright. So trying to make some head-way here. The List that I’m trying to save is a List… The BaseEnemy class is below…

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class BaseEnemy: MonoBehaviour {

    private StatCalculations statCalculationsScript = new StatCalculations();
    private CalculateXP calculateXPScript = new CalculateXP();

    public bool isAlive;
    public float timeOfDeath;
    public bool isCaptured;
    public int number;
    public string enemyName;
    public string description;
    public bool isFromTrade;
    public int level;
    public int evolveLevel;
    public Types.TypesList type01;
    public Types.TypesList type02;
    public Sexes.SexesList sex;
    public Natures.NaturesList nature;
    public string ability01;
    public string ability02;
    public int baseHP;
    public int baseATK;
    public int baseDEF;
    public int baseSPATK;
    public int baseSPDEF;
    public int baseSPD;
    public int maxHP;
    public int maxATK;
    public int maxDEF;
    public int maxSPATK;
    public int maxSPDEF;
    public int maxSPD;
    public int curHP;
    public int curATK;
    public int curDEF;
    public int curSPATK;
    public int curSPDEF;
    public int curSPD;
    public float evasion;
    public float accuracy;
    public int hpEV;
    public int atkEV;
    public int defEV;
    public int spatkEV;
    public int spdefEV;
    public int spdEV;
    public int hpIV;
    public int atkIV;
    public int defIV;
    public int spatkIV;
    public int spdefIV;
    public int spdIV;
    public int baseEXPYield;
    public LevelingRates.LevelingRatesList levelingRate;
    public int currentXP;
    public int requiredXP;
    public int hpEVYield;
    public int atkEVYield;
    public int defEVYield;
    public int spatkEVYield;
    public int spdefEVYield;
    public int spdEVYield;
    public int baseFriendship;
    public int catchRate;
    public StatusConditions.StatusConditionsList statusCondition;
    public List<BaseMove> enemyMoves = new List<BaseMove>();
    public BaseItem equippedItem;
    public BaseItem EquippedItem{
        get{return equippedItem;}
        set{equippedItem = value;}
    }

    public bool IsCaptured{
        get{return isCaptured;}
        set{isCaptured = value;}
    }
    public string EnemyName{
        get{return enemyName;}
        set{enemyName = value;}
    }
    public string Description{
        get{return description;}
        set{description = value;}
    }
    public bool IsFromTrade{
        get{return isFromTrade;}
        set{isFromTrade = value;}
    }
    public int Number{
        get{return number;}
        set{number = value;}
    }
    public int Level{
        get{return level;}
        set{level = value;}
    }
    public int EvolveLevel{
        get{return evolveLevel;}
        set{evolveLevel = value;}
    }
    public Types.TypesList Type01{
        get{return type01;}
        set{type01 = value;}
    }
    public Types.TypesList Type02{
        get{return type02;}
        set{type02 = value;}
    }
    public Sexes.SexesList Sex{
        get{return sex;}
        set{sex = value;}
    }
    public Natures.NaturesList Nature{
        get{return nature;}
        set{nature = value;}
    }
    public string Ability01{
        get{return ability01;}
        set{ability01 = value;}
    }
    public string Ability02{
        get{return ability02;}
        set{ability02 = value;}
    }
    public int BaseHP{
        get{return baseHP;}
        set{baseHP = value;}
    }
    public int BaseATK{
        get{return baseATK;}
        set{baseATK = value;}
    }
    public int BaseDEF{
        get{return baseDEF;}
        set{baseDEF = value;}
    }
    public int BaseSPATK{
        get{return baseSPATK;}
        set{baseSPATK = value;}
    }
    public int BaseSPDEF{
        get{return baseSPDEF;}
        set{baseSPDEF = value;}
    }
    public int BaseSPD{
        get{return baseSPD;}
        set{baseSPD = value;}
    }
    public int CurHP{
        get{return curHP;}
        set{curHP = value;}
    }
    public int CurATK{
        get{return curATK;}
        set{curATK = value;}
    }
    public int CurDEF{
        get{return curDEF;}
        set{curDEF = value;}
    }
    public int CurSPATK{
        get{return curSPATK;}
        set{curSPATK = value;}
    }
    public int CurSPDEF{
        get{return curSPDEF;}
        set{curSPDEF = value;}
    }
    public int CurSPD{
        get{return curSPD;}
        set{curSPD = value;}
    }
    public int MaxHP{
        get{return maxHP;}
        set{maxHP = value;}
    }
    public int MaxATK{
        get{return maxATK;}
        set{maxATK = value;}
    }
    public int MaxDEF{
        get{return maxDEF;}
        set{maxDEF = value;}
    }
    public int MaxSPATK{
        get{return maxSPATK;}
        set{maxSPATK = value;}
    }
    public int MaxSPDEF{
        get{return maxSPDEF;}
        set{maxSPDEF = value;}
    }
    public int MaxSPD{
        get{return maxSPD;}
        set{maxSPD = value;}
    }
    public float Evasion{
        get{return evasion;}
        set{evasion = value;}
    }
    public float Accuracy{
        get{return accuracy;}
        set{accuracy = value;}
    }
    public int HPEV{
        get{return hpEV;}
        set{hpEV = value;}
    }
    public int ATKEV{
        get{return atkEV;}
        set{atkEV = value;}
    }
    public int DEFEV{
        get{return defEV;}
        set{defEV = value;}
    }
    public int SPATKEV{
        get{return spatkEV;}
        set{spatkEV = value;}
    }
    public int SPDEFEV{
        get{return spdefEV;}
        set{spdefEV = value;}
    }
    public int SPDEV{
        get{return spdEV;}
        set{spdEV = value;}
    }
    public int HPIV{
        get{return hpIV;}
        set{hpIV = value;}
    }
    public int ATKIV{
        get{return atkIV;}
        set{atkIV = value;}
    }
    public int DEFIV{
        get{return defIV;}
        set{defIV = value;}
    }
    public int SPATKIV{
        get{return spatkIV;}
        set{spatkIV = value;}
    }
    public int SPDEFIV{
        get{return spdefIV;}
        set{spdefIV = value;}
    }
    public int SPDIV{
        get{return spdIV;}
        set{spdIV = value;}
    }
    public int BaseEXPYield{
        get{return baseEXPYield;}
        set{baseEXPYield = value;}
    }
    public LevelingRates.LevelingRatesList LevelingRate{
        get{return levelingRate;}
        set{levelingRate = value;}
    }
    public int CurrentXP{
        get{return currentXP;}
        set{currentXP = value;}
    }
    public int RequiredXP{
        get{return requiredXP;}
        set{requiredXP = value;}
    }
    public int HPEVYield{
        get{return hpEVYield;}
        set{hpEVYield = value;}
    }
    public int ATKEVYield{
        get{return atkEVYield;}
        set{atkEVYield = value;}
    }
    public int DEFEVYield{
        get{return defEVYield;}
        set{defEVYield = value;}
    }
    public int SPATKEVYield{
        get{return spatkEVYield;}
        set{spatkEVYield = value;}
    }
    public int SPDEFEVYield{
        get{return spdefEVYield;}
        set{spdefEVYield = value;}
    }
    public int SPDEVYield{
        get{return spdEVYield;}
        set{spdEVYield = value;}
    }
    public int BaseFriendship{
        get{return baseFriendship;}
        set{baseFriendship = value;}
    }
    public int CatchRate{
        get{return catchRate;}
        set{catchRate = value;}
    }
    public StatusConditions.StatusConditionsList StatusCondition{
        get{return statusCondition;}
        set{statusCondition = value;}
    }

    void Awake(){
        isAlive = true;
        SetupEnemy();
    }

    void Start(){
    }

    void Update(){
        SetupGrowingStats();
    }

    public void SetupEnemy(){
        SetupIV();
        ChooseEnemySex();
        ChooseEnemyNature();
        SetupStats();
    }

    private void SetupIV(){
        HPIV = Random.Range(0,15);
        ATKIV = Random.Range(0,15);
        DEFIV = Random.Range(0,15);
        SPATKIV = Random.Range(0,15);
        SPDEFIV = Random.Range(0,15);
        SPDIV = Random.Range(0,15);
    }

    private void ChooseEnemySex(){
        if(ATKIV > 2){
            Sex = Sexes.SexesList.MALE;
        }else if(ATKIV <= 2){
            Sex = Sexes.SexesList.FEMALE;
        }
    }
 
    private void ChooseEnemyNature(){
        System.Array natures = System.Enum.GetValues (typeof(Natures.NaturesList));
        Nature = (Natures.NaturesList)natures.GetValue (Random.Range(0,24));
    }

    private void SetupStats(){
        MaxHP = statCalculationsScript.CalculateHP (BaseHP, Level, HPIV, HPEV);
        MaxATK = statCalculationsScript.CalculateStat (BaseATK, Level, ATKIV, ATKEV, Nature, StatCalculations.StatTypes.ATTACK);
        MaxDEF = statCalculationsScript.CalculateStat (BaseDEF, Level, DEFIV, DEFEV, Nature, StatCalculations.StatTypes.DEFENSE);
        MaxSPATK = statCalculationsScript.CalculateStat (BaseSPATK, Level, SPATKIV, SPATKEV, Nature, StatCalculations.StatTypes.SPECIALATTACK);
        MaxSPDEF = statCalculationsScript.CalculateStat (BaseSPDEF, Level, SPDEFIV, SPDEFEV, Nature, StatCalculations.StatTypes.SPECIALDEFENSE);
        MaxSPD = statCalculationsScript.CalculateStat (BaseSPD, Level, SPDIV, SPDEV, Nature, StatCalculations.StatTypes.SPEED);
        CurHP = MaxHP;
        CurATK = MaxATK;
        CurDEF = MaxDEF;
        CurSPATK = MaxSPATK;
        CurSPDEF = MaxSPDEF;
        CurSPD = MaxSPD;
        Evasion = 1.0f;
        Accuracy = 1.0f;
        CurrentXP = calculateXPScript.CalculateCurrentXP(Level, LevelingRate);
        RequiredXP = calculateXPScript.CalculateRequiredXP(Level, LevelingRate);
    }

    public void AdjustCurrentHP(int adj){
        CurHP += adj;
        if(CurHP < 0){
            CurHP = 0;
        }
        if(CurHP > MaxHP){
            CurHP = MaxHP;
        }
    }
    public void AdjustCurrentATK(int adj){
        CurATK += adj;
        if(CurATK < 0){
            CurATK = 0;
        }
        if(CurATK > MaxATK){
            CurATK = MaxATK;
        }
    }
    public void AdjustCurrentDEF(int adj){
        CurDEF += adj;
        if(CurDEF < 0){
            CurDEF = 0;
        }
        if(CurDEF > MaxDEF){
            CurDEF = MaxDEF;
        }
    }
    public void AdjustCurrentSPATK(int adj){
        CurSPATK += adj;
        if(CurSPATK < 0){
            CurSPATK = 0;
        }
        if(CurSPATK > MaxSPATK){
            CurSPATK = MaxSPATK;
        }
    }
    public void AdjustCurrentSPDEF(int adj){
        CurSPDEF += adj;
        if(CurSPDEF < 0){
            CurSPDEF = 0;
        }
        if(CurSPDEF > MaxSPDEF){
            CurSPDEF = MaxSPDEF;
        }
    }
    public void AdjustCurrentSPD(int adj){
        CurSPD += adj;
        if(CurSPD < 0){
            CurSPD = 0;
        }
        if(CurSPD > MaxSPD){
            CurSPD = MaxSPD;
        }
    }

    public void AdjustEXP(int adj){
        CurrentXP += adj;
        if(CurrentXP >= RequiredXP){
            Level += 1;
            RequiredXP = calculateXPScript.CalculateRequiredXP(Level, LevelingRate);
            SetupGrowingStats();
        }
    }

    private void SetupGrowingStats(){
        MaxHP = statCalculationsScript.CalculateHP (BaseHP, Level, HPIV, HPEV);
        MaxATK = statCalculationsScript.CalculateStat (BaseATK, Level, ATKIV, ATKEV, Nature, StatCalculations.StatTypes.ATTACK);
        MaxDEF = statCalculationsScript.CalculateStat (BaseDEF, Level, DEFIV, DEFEV, Nature, StatCalculations.StatTypes.DEFENSE);
        MaxSPATK = statCalculationsScript.CalculateStat (BaseSPATK, Level, SPATKIV, SPATKEV, Nature, StatCalculations.StatTypes.SPECIALATTACK);
        MaxSPDEF = statCalculationsScript.CalculateStat (BaseSPDEF, Level, SPDEFIV, SPDEFEV, Nature, StatCalculations.StatTypes.SPECIALDEFENSE);
        MaxSPD = statCalculationsScript.CalculateStat (BaseSPD, Level, SPDIV, SPDEV, Nature, StatCalculations.StatTypes.SPEED);
        CurrentXP = calculateXPScript.CalculateCurrentXP(Level, LevelingRate);
        RequiredXP = calculateXPScript.CalculateRequiredXP(Level, LevelingRate);
    }

    public void SetDead(){
        this.isAlive = false;
        this.timeOfDeath = Time.time;

        ReSpawner.deadEnemy.Add(this);

        this.gameObject.SetActive(false);
    }
}

The List class is EnemyRoster…

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class EnemyRoster : MonoBehaviour {

    public List<BaseEnemy> enemyRoster = new List<BaseEnemy>();

    void Start () {
   
    }

    void Update () {
   
    }
}

This is what I’ve come across so far. I found this in Unity Answers…

 public static string ObjectToStr<T> (T _saveMe)
     {
         BinaryFormatter _bin = new BinaryFormatter ();
         MemoryStream _mem = new MemoryStream ();
         _bin.Serialize (_mem, _saveMe);
      
         return Convert.ToBase64String (
             _mem.GetBuffer ()
         );
     }
  
     public static T StrToObject<T> (string _data) where T : class
     {
         if (!String.IsNullOrEmpty (_data)) {
             BinaryFormatter _bin = new BinaryFormatter ();
             try {
                 MemoryStream _mem = new MemoryStream (Convert.FromBase64String (_data));
              
                 T _obj = _bin.Deserialize (_mem) as T;
  
                 return _obj;
             } catch (Exception ex) {
                 throw new Exception (ex.Message);
             }
          
         } else {
             throw new Exception ("_data is null or empty");
         }
     }

Saving

PlayerPrefs.SetString ("KeyName", Helpers.ObjectToStr<List<*TYPE*>> (serializableObj));

Loading

 List<*TYPE*> _myserializableObj = Helpers.StrToObject<List<*TYPE*>> (PlayerPrefs.GetString ("KeyName"));

However, due to the lack of commenting in that code, I’m not sure what I’d have to change to make it suit my needs. Any help?

Okay. Came up with this so far.

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public class GameMaster : MonoBehaviour {
   
    public Camera mainCamera;

    private GameObject playerCharacter;
    private GameObject headsUpDisplay;
    private GameObject eventSystem;
    private GameObject pc;
    private GameObject cam;
    private PlayerCharacter pcScript;
    private Vector3 playerSpawnPointPos;

    void Awake(){
        DontDestroyOnLoad(this);
    }

    void Start () {
        playerSpawnPointPos = ChooseSpawnPoint.PickSpawnPoint(Application.loadedLevelName.ToString(), PlayerPrefs.GetString("Last Zone", "Town"));
        playerCharacter = (GameObject)Resources.Load("Prefabs/Player Character Prefab");
        pc = Instantiate(playerCharacter, playerSpawnPointPos, Quaternion.identity) as GameObject;
        if(Application.loadedLevelName == "Main Menu" || Application.loadedLevelName == "Character Generation"){
            pc.GetComponent<Movement>().enabled = false;
            pc.GetComponent<BallThrow>().enabled = false;
            pc.GetComponent<Encounter>().enabled = false;
        }
        pc.name = "Player Character";
        pcScript = pc.GetComponent<PlayerCharacter>();
        cam = Instantiate(mainCamera, Vector3.zero, Quaternion.identity) as GameObject;
        if(Application.loadedLevelName != "Main Menu" || Application.loadedLevelName != "Character Generation"){
            LoadCharacterData();
            headsUpDisplay = (GameObject)Resources.Load("Prefabs/HUD Prefab");
            eventSystem = (GameObject)Resources.Load("Prefabs/Event System Prefab");
            Instantiate(headsUpDisplay, Vector3.zero, Quaternion.identity);
            Instantiate(eventSystem, Vector3.zero, Quaternion.identity);
        }
        pcScript.LastZone = Application.loadedLevelName.ToString();
        SaveCharacterData();
    }

    public static string ObjectToStr<BaseEnemy> (BaseEnemy _saveMe)
    {
        BinaryFormatter _bin = new BinaryFormatter ();
        MemoryStream _mem = new MemoryStream ();
        _bin.Serialize (_mem, _saveMe);
       
        return Convert.ToBase64String (_mem.GetBuffer());
    }
    public static BaseEnemy StrToObject<BaseEnemy> (string _data) where BaseEnemy : class
    {
        if (!String.IsNullOrEmpty (_data)) {
            BinaryFormatter _bin = new BinaryFormatter ();
            try {
                MemoryStream _mem = new MemoryStream (Convert.FromBase64String (_data));
               
                BaseEnemy _obj = _bin.Deserialize (_mem) as BaseEnemy;
               
                return _obj;
            } catch (Exception ex) {
                throw new Exception (ex.Message);
            }
           
        } else {
            throw new Exception ("_data is null or empty");
        }
    }

    public void SaveCharacterData(){
        GameObject pc = GameObject.Find("Player Character");
        PlayerCharacter pcClass = pc.GetComponent<PlayerCharacter>();
        EnemyRoster pcERoster = pc.GetComponent<EnemyRoster>();
        EnemyInventory pcEInventory = pc.GetComponent<EnemyInventory>();
       
        PlayerPrefs.SetString("Player Name", pcClass.PlayerName);
        PlayerPrefs.SetInt("Player Sex", (int)pcClass.PlayerSex);
        PlayerPrefs.SetInt("Player Money", pcClass.PlayerMoney);
        PlayerPrefs.SetString("Last Zone", pcClass.LastZone);
        PlayerPrefs.SetString ("EnemyRoster", ObjectToStr<List<BaseEnemy>> (pcERoster.enemyRoster));
        PlayerPrefs.SetString ("EnemyInventory", ObjectToStr<List<BaseEnemy>> (pcEInventory.enemyInventory));
    }

    public void LoadCharacterData(){
        GameObject pc = GameObject.Find("Player Character");
        PlayerCharacter pcClass = pc.GetComponent<PlayerCharacter>();
        EnemyRoster pcERoster = pc.GetComponent<EnemyRoster>();
        EnemyInventory pcEInventory = pc.GetComponent<EnemyInventory>();

        pcClass.PlayerName = PlayerPrefs.GetString("Player Name", "Name Me");
        pcClass.PlayerSex = (Sexes.SexesList)PlayerPrefs.GetInt("Player Sex", 0);
        pcClass.PlayerMoney = PlayerPrefs.GetInt("Player Money", 0);
        pcClass.LastZone = PlayerPrefs.GetString("Last Zone", "Pallet Town");
        pcERoster.enemyRoster = StrToObject<List<BaseEnemy>> (PlayerPrefs.GetString ("EnemyRoster"));
        pcEInventory.enemyInventory = StrToObject<List<BaseEnemy>> (PlayerPrefs.GetString ("EnemyInventory"));
    }

}

And I’m getting this error…

SerializationException: Type UnityEngine.MonoBehaviour in assembly UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.
System.Runtime.Serialization.FormatterServices.GetSerializableMembers (System.Type type, StreamingContext context) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization/FormatterServices.cs:101)
System.Runtime.Serialization.Formatters.Binary.CodeGenerator.GenerateMetadataTypeInternal (System.Type type, StreamingContext context) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs:78)
System.Runtime.Serialization.Formatters.Binary.CodeGenerator.GenerateMetadataType (System.Type type, StreamingContext context) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs:64)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.CreateMemberTypeMetadata (System.Type type) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:442)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.GetObjectData (System.Object obj, System.Runtime.Serialization.Formatters.Binary.TypeMetadata& metadata, System.Object& data) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:430)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteObject (System.IO.BinaryWriter writer, Int64 id, System.Object obj) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:306)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteObjectInstance (System.IO.BinaryWriter writer, System.Object obj, Boolean isValueObject) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:293)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteQueuedObjects (System.IO.BinaryWriter writer) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:271)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteObjectGraph (System.IO.BinaryWriter writer, System.Object obj, System.Runtime.Remoting.Messaging.Header[ ] headers) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:256)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[ ] headers) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:232)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:211)
GameMaster.ObjectToStr[List`1] (System.Collections.Generic.List`1 _saveMe) (at Assets/Scripts/Game Master/GameMaster.cs:58)
GameMaster.SaveCharacterData () (at Assets/Scripts/Game Master/GameMaster.cs:91)
CharacterGeneratorGUI.LetsGo () (at Assets/Scripts/GUIs/CharacterGeneratorGUI.cs:128)
UnityEngine.Events.InvokableCall.Invoke (System.Object[ ] args) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:109)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[ ] parameters) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:575)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[ ] parameters) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:717)
UnityEngine.Events.UnityEvent.Invoke () (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()

Not to discourage you, both the BaseEnemy class and GameMaster class appear to be horrible spaghetti code mashed together from random snippets found on the internet :).

Other than advising an exorcism, I suggest you clean up your initial BaseEnemy class, and instead of manual binary formatting to playerprefs, use JSON.net, which will serialise a class for you (not a monobehaviour derived class mind you), in literally one line of code. There is no point of reinventing the wheel.

Remember for this you need a non monobehaviour class to serialise properly, it can serialise lists, lists of lists, classic arrays, and most other things, automatically, into a nicely JSON formatted string, which I would write to file if I were you.

BaseEnemy is entirely from scratch, but GameMaster does derive from a few tutorials.

Can it serialize a list of classes that derive from monobehaviour though?

No it can’t, you need to transfer that information to another class to be saved, or store it in a non monobehaviour class instanced inside of your monobehaviour class.

…aaaaaaaand I think that is beyond my scope sadly. :frowning:

haha It is less complicated that what you wrote there to be honest. Other than that I can only recommend an SQLITE database, that can get even more complicated though.

EDIT:
Or pay someone to write it for you…

Well…what I wrote there came from THIS Unity Answers page…