My game uses the PlayerPrefs file to save important info of characters like health. The problem is that anybody can get into the file by going to the directory, and when they get there, they can edit the info to cheat and such. Is there a way to hide the variables in the PlayerPref’s file so that people can’t see the variable with the naked eye? If not, is there a way thats similar?
If you want a good way of saving data and keeping players from cheating, I would recommend using binary serialization. It’s very easy to set up, and creates a nice save file in binary, so players can’t edit it. Heres one that I wrote.
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public static class BinarySerializer {
public static void serialize<T>(T data, string filePath) {
Stream stream = File.Open(filePath, FileMode.Create);
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Binder = new VersionDeserializationBinder();
binaryFormatter.Serialize(stream, data);
stream.Close();
}
public static T deserialize<T>(string filePath) {
try {
Stream stream = File.Open(filePath, FileMode.Open);
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Binder = new VersionDeserializationBinder();
T data = (T)binaryFormatter.Deserialize(stream);
stream.Close();
return data;
}
catch (FileNotFoundException exception) {
throw exception;
}
}
}
And this second class is just to make sure the save files can be loaded after unity recompiles scripts
using System.Runtime.Serialization;
using System.Reflection;
public class VersionDeserializationBinder : SerializationBinder {
public override System.Type BindToType(string assemblyName, string typeName) {
if (!string.IsNullOrEmpty(assemblyName) && !string.IsNullOrEmpty(typeName)) {
System.Type typeToDeserialize = null;
assemblyName = System.Reflection.Assembly.GetExecutingAssembly().FullName;
typeToDeserialize = System.Type.GetType(string.Format("{0}, {1},", typeName, assemblyName));
return typeToDeserialize;
}
return null;
}
}
And heres an example class that can be serialized and deserialized.
using UnityEngine;
using System.Collections;
using System.Runtime.Serialization;
[System.Serializable()]
public class MySaveData : ISerializable {
public int savedInt = 0;
public MySaveData() {}
public MySaveData(SerializationInfo info, StreamingContext context) {
savedInt = (int)info.GetValue("savedInt", typeof(int));
}
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("savedInt", savedInt);
}
}
And here is an example showing how to save and load a file
MySaveData saveData = new MySaveData();
saveData.savedInt = 12345;
string filePath = "blah/blah/blah"
//Saves saveData
BinarySerializer.serialize<MySaveData>(saveData, filePath);
//Load saveData
saveData = BinarySerializer.deserialize<MySaveData>(filePath);
You can use ArrayPrefs2 to save data with PlayerPrefs, where values are converted to bytes which are stored as strings using Base64. Technically they can still be edited, but would be much harder (for non-programmers anyway). Also, even if you’re not actually using arrays, you can make a dummy array and hide the “real” value in it, which would further increase the difficulty.