Save/Load High Scores

Started by
18 comments, last by Kk1496 8 years, 7 months ago
I've used the live training on persistent data to save an array of high scores. However, when using the script i receive this error.

NullReferenceException: Object reference not set to an instance of an object Timer.Update () (at Assets/Scripts/Timer.cs:50)

The code it is talking about looks like this:

if (gameTimer <= 0)
{
inGame.SetActive (false);
playArea.SetActive (false);
gameOver.SetActive (true);
finalScore.text = "Score: " + GameManager.score;
Manager.gameManager.Save();
}

It seems to be talking about the save function that looks like this:

public void Save ()
{
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Create (Application.persistentDataPath + "/HihgScores.dat");

HighScores hScore = new HighScores ();
foreach(int score in hScore.highScores)
{
if (GameManager.score >= hScore.highScores[score])
{
hScore.highScores[score] = GameManager.score;
break;
}
}

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

The class that this method is from has a public static version of itself (like the live training says) so I'm not sure why it can't find a reference to the game object since it's persisting in all scenes.
Advertisement

On which line does the error occur?

You're instantiating a new HighScores instance (hScore). Unless the constructor for HighScores populates itself with data (?) there will be nothing to dereference at the following line:

if (GameManager.score >= hScore.highScores[score])

because hScore.highScores (an array or list I'm assuming) hasn't been populated with any content. For all we know, hScore.highScores itself is still null.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

So, the class that I am serializing should handle the array as far as population and sorting? I had only one score saved (not an array) just to get things working. Now that it works (I eventually solved the error, the file name string didn't match in load ;( ) how would I turn this into a leaderboard? I u derstand how to manage the player's high scores, but how could you manage this for multiple users? I've seen this done in tiny wings where I think you can change the user name in settings and it'll change your high scores accordingly. I'd also like to integrate this with facebook eventually.


how could you manage this for multiple users?

Off-the-cuff here, but a high level version would be if you want the scoreboard to reflect local players only, the game can just load up the external .dat file when you start the game (so the current high scores are in memory), and then save it back out on exit with any changes.

If you want it integrated to facebook and reflecting multiple remote users, that .dat file will need to live somewhere all the FB instances can access it, or be converted to a database table (with interface changes in the code as well as you'd no longer be loading in from a file stream).

If you want it integrated to facebook but still only want to track the local players' high scores, you can save some kind of file off into browser cache/cookies.

There are other solutions as well, my web-stack experience is much shorter than my desktop/enterprise knowledge.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

I thought I knew what I was doing when I converted that test high score to an array but I guess not.

public void Save ()
{
Debug.Log ("Save() was called");
if (!File.Exists (Application.persistentDataPath + "/HihgScores.dat"))
{
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Create (Application.persistentDataPath + "/HihgScores.dat");
HighScores hScore = new HighScores ();
hScore.highScores = highScores;
bf.Serialize (file, hScore);
file.Close ();
}
else {
Load ();
}
}

public void Load ()
{
Debug.Log ("Load() was called");
if (File.Exists (Application.persistentDataPath + "/HihgScores.dat"))
{
//Debug.Log ("File Exists");
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Open (Application.persistentDataPath + "/HihgScores.dat", FileMode.Open);
HighScores hScore = (HighScores)bf.Deserialize (file);
System.Array.Copy(hScore.highScores, highScores, 10);
file.Close ();
//Debug.Log ("High Score: " + HighScoreManager.highScore);
}
//Debug.Log ("Exiting Load()");
}

[Serializable]
class HighScores
{
public int[] highScores = new int[10];
}

These changes now cause this error:

ArgumentException: Object type System.Int32 cannot be converted to target type: System.Int32[]

Parameter name: val
I'm now calling Load() n Awake() and Save() in ONApplicationQuit() on my overall game manager which persists throughout all scenes if that helps any.
I've tried googling this error but theI don't quite understand the explanation.


ArgumentException: Object type System.Int32 cannot be converted to target type: System.Int32[]

"An integer can't be converted to an array of integers"
Which line is throwing that error?

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

That's the weird part. When I double click the error nothing happens. Shouldn't it highlight in mono?

There should be more information in the Console tab/window, to include the full stack-trace of the error/output (when you select any entry in the Console list, i.e. one left click). Each entry in the trace should tell you which file it was in for that step, and which line the function call for that step happens at. Resize the console tab to see more (as the stacktrace content appears at the bottom of the window), or just highlight the whole mess and paste it into a notepad or something to read.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

Wow...
ArgumentException: Object type System.Int32 cannot be converted to target type: System.Int32[]
Parameter name: val
System.Reflection.MonoField.SetValue (System.Object obj, System.Object val, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoField.cs:133)
System.Reflection.FieldInfo.SetValue (System.Object obj, System.Object value) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/FieldInfo.cs:150)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.SetObjectValue (System.Object parentObject, System.String fieldName, System.Reflection.MemberInfo memberInfo, System.Runtime.Serialization.SerializationInfo info, System.Object value, System.Type valueType, System.Int32[] indices) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:799)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadValue (System.IO.BinaryReader reader, System.Object parentObject, Int64 parentObjectId, System.Runtime.Serialization.SerializationInfo info, System.Type valueType, System.String fieldName, System.Reflection.MemberInfo memberInfo, System.Int32[] indices) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:721)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectContent (System.IO.BinaryReader reader, System.Runtime.Serialization.Formatters.Binary.TypeMetadata metadata, Int64 objectId, System.Object& objectInstance, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:306)
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-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:270)
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-runtime-and-classlibs/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-runtime-and-classlibs/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-runtime-and-classlibs/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-runtime-and-classlibs/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-runtime-and-classlibs/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-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:136)
Manager.Load () (at Assets/Scripts/Manager.cs:58)
Manager.Awake () (at Assets/Scripts/Manager.cs:20)

All this seems to be telling me is that there is a problem where save and load are called.

This topic is closed to new replies.

Advertisement