1

I'm currently encountering an error in a large scale project.

Code below:

public void SaveFileExists(){

    Debug.Log ("SaveFileExists was called.");

    //GameObject.Find ("_Scripts").GetComponent<SaveGame> ().Load ();
    UserData userdata = null;

    //Creating a new BinaryFormatter
    BinaryFormatter bf = new BinaryFormatter ();

    //Making a file which now contains the Un-Serialized File
    FileStream file = File.Open (Application.persistentDataPath + ("/UserData." + accountLoginAttempt), FileMode.Open);

    //Assigning the values of the saved file to the new file
    //UserData newData = (UserData)bf.Deserialize (file);

    userdata = bf.Deserialize(file) as UserData;

    //Assigning the values from the save file to the variables in this script.
    accountLoginAttempt = userdata.username;
    accountLevel = userdata.userlevel;

    //Assinging the values from this script to the _PlayerManager script. (This is where the UI gets it's info).
    GameObject.Find ("_AccountInfoSaveHolder").GetComponent<HoldInfo> ().UserInfo = accountLoginAttempt;
    GameObject.Find ("_AccountInfoSaveHolder").GetComponent<HoldInfo> ().UserLevel = accountLevel;

    errortext.text = "Login Successful.";
    Canvas.ForceUpdateCanvases ();
}

The serialised field is also below:

[System.Serializable]
class UserData{
public string username;
public int userlevel;
}

I am trying to load a savefile which is stored in the Application.persistentDataPath. Assigning the UserData.username and UserData.userlevel to variables in my script.

The error I am receiving is:

InvalidCastException: Cannot cast from source type to destination type.

Further Details:

LoginScript.SaveFileExists () (at Assets/Scripts/AccountSystem/LoginScript.cs:126) LoginScript.OnLoginClick () (at Assets/Scripts/AccountSystem/LoginScript.cs:104) UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:153) UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:634) UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:769) UnityEngine.Events.UnityEvent.Invoke () (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53) UnityEngine.UI.Button.Press () (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44) UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52) UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269) UnityEngine.EventSystems.EventSystem:Update()

EDIT:

SaveGame.cs:

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

public class SaveGame : MonoBehaviour {

//Saved Variables
[Header("Saved Variables")]
public string savedname;
public string attemptedlogin;
public int savedlevel;

//Loaded Variables
[Header("Loaded Variables")]
public string loadedname;
public int loadedlevel;


public void Awake(){

    if (SceneManager.GetActiveScene ().name == "GameScene") {
        Load ();
    }
}

public void Save(){

    savedname = GameObject.Find ("_Scripts").GetComponent<PlayerManager> ().PlayerName;
    savedlevel = GameObject.Find ("_Scripts").GetComponent<PlayerManager> ().UserLevel;

    BinaryFormatter bf = new BinaryFormatter();

    FileStream file = File.Open(Application.persistentDataPath + ("/UserData." + savedname), FileMode.Create);

    UserData newData = new UserData();

    newData.username = savedname;
    newData.userlevel = savedlevel;

    bf.Serialize(file, newData);
    file.Close();
}
}

I also removed all System.Serializable class's throughout my scripts and made a script called UserDataSerialize.cs which contains:

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

[System.Serializable]
class UserData{
    public string username;
    public int userlevel;
}

Now the error I get is:

TypeLoadException: Could not load type 'SaveGame+UserData'.
System.Reflection.Assembly.GetType (System.String name, Boolean throwOnError, Boolean ignoreCase) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/Assembly.cs:398)
System.Reflection.Assembly.GetType (System.String name, Boolean throwOnError) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/Assembly.cs:381)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetDeserializationType (Int64 assemblyId, System.String className) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:833)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadTypeMetadata (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:637)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectInstance (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:269)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:195)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:223)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (BinaryElement element, System.IO.BinaryReader reader) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:130)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:104)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:179)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:136)
LoginScript.SaveFileExists () (at Assets/Scripts/AccountSystem/LoginScript.cs:111)
LoginScript.OnLoginClick () (at Assets/Scripts/AccountSystem/LoginScript.cs:84)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:153)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:634)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:769)
UnityEngine.Events.UnityEvent.Invoke () (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()
22
  • The only explicit cast is the result of BinaryFormatter.Deserialize to type UserData. Are you sure the file is in the format you expect? Commented Jun 20, 2017 at 5:55
  • @AndyLamb I think so? What exactly do you mean by the format it is expected. The class 'UserData' is a string 'username' followed by an int 'userlevel'. Commented Jun 20, 2017 at 6:08
  • What is your Unity version? Can you also put your save code in your question? Commented Jun 20, 2017 at 6:08
  • Unity 5.5.1f1 Personal (64bit) on Mac. SaveGame.cs: public void InitializeSave(){ savedname = GameObject.Find ("_Scripts").GetComponent<PlayerManager> ().PlayerName; savedlevel = GameObject.Find ("_Scripts").GetComponent<PlayerManager> ().UserLevel; Save (); } MORE CODE IN NEXT COMMENT Commented Jun 20, 2017 at 6:10
  • Part 2 public void Save(){ BinaryFormatter bf = new BinaryFormatter(); //Creates a new file at the directory of the save path. FileStream file = File.Open(Application.persistentDataPath + ("/UserData." + savedname), FileMode.Create); //Clearing temp files and starting from a new file UserData newData = new UserData(); //Assigning Variables newData.username = savedname; newData.userlevel = savedlevel; //Encodes newData to file. bf.Serialize(file, newData); file.Close(); } Commented Jun 20, 2017 at 6:13

2 Answers 2

1

Solution:

Create another script which only contains:

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

[System.Serializable]
class UserData{
    public string username;
    public int userlevel;
}

And delete all other System.Serialize class's of the same name throughout other scripts.

Sign up to request clarification or add additional context in comments.

1 Comment

Great. Funny how that works in Unity 5.6 but not in 5.5. I guess Unity has fixed this problem.
0

Maybe not a problem for everyone, but this helped me: In the course of building my save structure, I first saved one type of object, but then switched to a different one. My game was set to load before there was an opportunity to save, and so I was loading an old class without having saved over it with the new class. I was able to resolve the problem by disabling load, playing the game for a turn, saving, and then turning load on again.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.