0
\$\begingroup\$

I've been working on an saving system for my 2D RPG game, and I recently encountered an issue: my saving system uses PlayerPrefs, which I heard is supposed to be used for things such as settings. I've also heard that it isn't very secure and that people can exploit it. I was wondering whether there was a way to make my saving system more secure. Here's my inventory script that also holds the save function:

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

public class ItemInformation : MonoBehaviour
{
    // These are the assets for the item to change
    public Text nameText;
    public Text descriptionText;
    public Text regenText;
    public Text amountText;

    // This is the identifier for each item
    public string identifier;

    // These are the variables that change with the different items
    public string itemName;
    public string itemDescription;
    public float itemRegeneration;
    public int itemAmount;
    
    // Starts on awake
    void Awake()
    {
        // Function to change the object's information and such
        nameText.text = itemName;
        descriptionText.text = itemDescription;
        regenText.text = "HEALS " + itemRegeneration + "HP";

        // Loads game data
        LoadDataIfNeeded();
    }

    // Function to save game data
    public void SaveData()
    {
        string jsonString = JsonUtility.ToJson(this);
        PlayerPrefs.SetString(identifier, jsonString);
        PlayerPrefs.Save();
    }

    // Loads data if needed
    public void LoadDataIfNeeded()
    {
        if (PlayerPrefs.HasKey(identifier))
        {
            string jsonInstance = PlayerPrefs.GetString(identifier);
            JsonUtility.FromJsonOverwrite(jsonInstance, this);
        }
        else
        {
            SaveData();
        }
    }

    // Updates on every frame
    void Update()
    {
        // Shows amount of item left
        amountText.text = "HAVE:" + itemAmount;
    }
}
\$\endgroup\$
9
  • \$\begingroup\$ If this is for an offline game, you can make it only harder for the player but never prevent. If it is an online game, store it server side to a database. \$\endgroup\$
    – Zibelas
    Commented Jan 18, 2021 at 14:32
  • \$\begingroup\$ @Zibelas It is an offline game. \$\endgroup\$ Commented Jan 18, 2021 at 14:36
  • \$\begingroup\$ @noobprogrammer Then what are you worrying about? When people hack their savegames, then the worst case is that they ruin their game experience. But they have no one to blame for that but themselves because every player should know that savegame hacking isn't the way you are supposed to play a game. But the best case is that they figure out how to create interesting situations they couldn't create otherwise and find completely new ways to squeeze even more enjoyment out of your game. \$\endgroup\$
    – Philipp
    Commented Jan 18, 2021 at 14:57
  • \$\begingroup\$ @Philipp Ok, thanks! Maybe I could even put some secret stuff that you can’t get to unless you modify some hidden variable. :) \$\endgroup\$ Commented Jan 18, 2021 at 15:06
  • \$\begingroup\$ Players might even use savegame editing to work around your bugs and design problems. When a player finds themselves in a softlocked state (due to a bug or design oversight on your part) but no older savegame to load from, then they might rescue their run by modifying their savegame. Sure, the ideal solution would be for you to patch that problem, but that might take you some time. \$\endgroup\$
    – Philipp
    Commented Jan 18, 2021 at 15:07

2 Answers 2

3
\$\begingroup\$

Since you wrote in a comment it is for an offline game, the short answer is: you can't.

If the player is the owner of the whole game (since it offline), any kind of mechnism can be prevented if he is dedicated enough to figure out how you obscured your data. You can only make it harder for him.

You need to prevent memory manipulation, else the player could either freeze his hitpoints, ammo, money, etc or increase it to his liking.

The second part is you need to protect the save file itself against manipulation. Since he can read it as well, you need to make it harder for him to read and change values. Binary files, custom formats and a hash of everything are doing the job. The draw back (if that is one for you) is, if he really tries to manipulate the file, he might create new run time errors when you try to read your own file since the format got broken (and the player will certainly blame it on you why all his items are gone)

There is the opinion that if the game is offline, you should let the player do what he wants. Maybe the game is too hard and he would otherwise stop playing. Maybe he is lacking time for farming. As long as he is the only player, all he can do is boost himself and has no effect on the play experience of other players.

\$\endgroup\$
0
\$\begingroup\$

First, I'd not recommend saving in PlayerPrefs for large saves, it would be better to save it in a file at PersistentDataPath instead.

As for preventing the player from modifying it, the simplest way would be to encrypt the file before saving it to the disk, and then decrypt it when loading. The encryption key would be hard-coded to your program so there wouldn't be any external file that the player can access in order to easily decode and modify your save file, but any decompiler can easily see your program's code and extract that key. It would require some more technical know-how, so most simple players would not be able to do that.

You can go even further by using a native plugin to hide your encryption key in, and add complex code that generates the key real-time (instead of simply entering a string which hackers can easily find).

All that said - if it's a single player game, there's no real reason to work so hard to prevent cheating. A simple encrypted save file will be very easy to implement and will do the trick nicely for most cases. Even that may be too much since if a player decided they want to cheat, why do you care, whatever makes the game more fun for them should be good for you.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .