Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question other ways to store usable items besides playerprefs

Discussion in 'Scripting' started by ANickerson, May 12, 2021.

  1. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11
    I am developing a simple game that has 3 different special items you can apply before the level starts, I was going to use playerprefs for keeping the amount of these items the player has but I have read on a handful of threads that playerprefs isn't ideal for this because people can access the playerprefs and change the value if they know how.

    so whats the best method to do this? I have a rewarded ads button to give them the items and also an IAP option, so i need to be able to keep that from being messed with by the players and also have the game keep track of how many the player has and also deduct from that amount when they chose to use them for a level

    thanks for any help that can be provided!
     
  2. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    Beware that players can access ANYTHING on their computer and change it regardless of how much you encrypt it. You're welcome to hate this fact or love it, and you're welcome to pour more oceans of digital ink into arguing this point, but it actually doesn't matter how much you write about it: the player's computer is NOT a trusted computer to you. All time you spend attempting to secure it is in vain, and is time better spent making your game.

    That said, if it's a few numbers, put it in PlayerPrefs. If it's a huge block of state, write it to disk.
     
  4. Stevens-R-Miller

    Stevens-R-Miller

    Joined:
    Oct 20, 2017
    Posts:
    664
    I'd go with disk in all cases. On anything other than Windows, that's where PlayerPrefs stuff goes anyway. Strictly speaking, it goes to disk on Windows, too, since that's where the registry is recorded.

    You can encrypt, obfuscate, make redundant copies of, and otherwise try to hide your data. But I agree with Kurt that, at some point, you have to accept the fact that the player can probably beat your system. Now, for a single-player game, do you really care? If the player wants to skip to the end, or give themselves a million lives, or whatever, that's really their loss. It just means they are subverting the game they paid you to play.

    In an online multiplayer game, however, that kind of thing can mean cheating in ways that damage the experience of honest players. For that, you need to have a server under your control where precious data is kept secure. Or, at least, offer a group of players the chance to designate a host, and hope they can pick someone trustworthy. Even networked games with servers can't stop all cheating. For example, if your game has day/night modes, and "night" means "can't see very far," a player might find a flag in their local run-time code that flip between modes. With enough filtering and some trial-and-error, they could eventually find the one byte that lets them turn night into day, while everyone else is still playing in the dark. Writing the code to detect that kind of cheat is a challenge which, alas, the big shops have realized they need to do. For us little guys, I think it's kind of pointless to try. We have too much else to do, and not enough time to do it.
     
    Kurt-Dekker and MartinMa_ like this.
  5. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11
    Yes I understand that nothing is completely secure, there are resourceful people out there that can get into anything.

    It's a simple single player mobile game so I'm not going to lose sleep over it, I was just trying to find something a little more secure than the PlayerPrefs.

    The video shared seems like it will work and I'm following along but I am getting an error when the guy who made the video did not so I'll have to figure out where I went wrong
     
  6. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11
    Code (CSharp):
    1. using UnityEngine;
    2. using System.IO;
    3. using System.Runtime.Serialization.Formatters.Binary;
    4.  
    5. public static class SaveSystem
    6. {
    7.     public static void SaveItems(Items items)
    8.     {
    9.         BinaryFormatter formatter = new BinaryFormatter();
    10.  
    11.         string path = Application.persistentDataPath + "/items.bin";
    12.         FileStream stream = new FileStream(path, FileMode.Create);
    13.  
    14.         ItemData data = new ItemData(items);
    15.  
    16.         formatter.Serialize(stream, data);
    17.         stream.Close();
    18.     }
    19.  
    20.     public static ItemData LoadItems()
    21.     {
    22.         string path = Application.persistentDataPath + "/items.bin";
    23.        
    24.         if (File.Exists(path))
    25.         {
    26.             BinaryFormatter formatter = new BinaryFormatter();
    27.             FileStream stream = new FileStream(path, FileMode.Open);
    28.  
    29.             ItemData = formatter.Deserialize(stream) as ItemData;
    30.             stream.Close();
    31.  
    32.             return ItemData;
    33.         }
    34.         else
    35.         {
    36.             Debug.LogError("Save file not found in" + path);
    37.             return null;
    38.         }
    39.     }
    40. }
    ok so I replaced "Player" in the videos example for "Items" because it made more sense for what I'm using it for and this is the error:

    Assets\SaveSystem.cs(7,34): error CS0246: The type or namespace name 'Items' could not be found (are you missing a using directive or an assembly reference?)


    any suggestions?
     
  7. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    You call your Save method with (Items items) that mean in your namespace you must have some script Items where is public variable for save.

    Can you post your Items and gamedata script?

    Code (CSharp):
    1. public static void SaveItems(Items items)
    By this method you say something like , take my variable from Items script and make game data from it.

    Best way how to use tutorial like this is to follow 100% of steps and when it start working then you can try change something.
     
    Last edited: May 12, 2021
  8. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11
    ok so i figured that part out and created that Items script and am now getting different errors

    Assets\SaveSystem.cs(14,38): error CS1503: Argument 1: cannot convert from 'Items' to 'ItemData'

    Assets\SaveSystem.cs(29,13): error CS0118: 'ItemData' is a type but is used like a variable

    Assets\SaveSystem.cs(32,20): error CS0103: The name 'Data' does not exist in the current context

    i am very new to unity so it may be something simple I'm missing
     
  9. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455

    What about your game data script from tutorial?
     
  10. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Should look like somezthing like this in your case name of script will be Itemdata since you changed that too

    Code (CSharp):
    1.  
    2.  
    3.     [System.Serializable]
    4.     public class GameData
    5.     {
    6.         //This is variable you want save
    7.  
    8.         public GalaxyObject _gO;
    9.  
    10.         //This is method what take variablo gO from my script TerrainManager
    11.         public GameData(TerrainManager terrainManager)
    12.         {
    13.  
    14.             _gO = terrainManager.gO;
    15.         }
    16.  
    17.     }
    18. }
     
  11. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11
    when I went back to copy that i saw it autofilled when i was writing that script and messed up there, here is the corrected version of that which did get rid of the first error:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [System.Serializable]
    6. public class ItemData
    7. {
    8.     public int FaceMask;
    9.     public int Goggles;
    10.     public int FaceShield;
    11.  
    12.     public ItemData (Items items)
    13.     {
    14.         FaceMask = items.FaceMask;
    15.         Goggles = items.Goggles;
    16.         FaceShield = items.FaceShield;
    17.     }
    18.  
    19. }
     
  12. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11

    so did i put the [System.Serializable] in the wrong place?
     
  13. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455

    Ii cant see any issue here it should work
     
  14. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    I see your problem in load method replace

    Code (CSharp):
    1.   ItemData = formatter.Deserialize(stream) as ItemData;
    2.             stream.Close();
    3.             return ItemData;
    4.  
    5.  
    Code (CSharp):
    1.   ItemData  data = formatter.Deserialize(stream) as ItemData;
    2.             stream.Close();
    3.             return data;
     
  15. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    This working for me
    Code (CSharp):
    1.        public static GameData LoadGalaxy()
    2.         {
    3.          
    4.          
    5.             string directoryPath = GenerateManager.galaxyPath;
    6.            
    7.  
    8.             if (Directory.Exists(directoryPath))
    9.             {
    10.                 string galaxyPath;
    11.  
    12.                 DirectoryInfo di = new DirectoryInfo(directoryPath);
    13.                 FileInfo[] fi = di.GetFiles("*.pgpro");
    14.                 foreach (FileInfo item in fi)
    15.                 {
    16.                     galaxyPath = item.FullName;
    17.                     BinaryFormatter formatter = new BinaryFormatter();
    18.                     FileStream stream = new FileStream(galaxyPath, FileMode.Open);
    19.  
    20.                     GameData savedGalaxy = formatter.Deserialize(stream) as GameData;
    21.                     stream.Close();
    22.                     return savedGalaxy;                  
    23.                 }
    24.                 return null;
    25.                            
    26.             }
    27.             else
    28.             {
    29.  
    30.                 return null;
    31.             }
    32.         }
     
  16. ANickerson

    ANickerson

    Joined:
    Mar 3, 2021
    Posts:
    11
    all errors gone thanks!