0

I started using PlayerPrefs in Unity and everything worked perfectly. Then I tried to build the game to send it to a friend. But as I tested it one more time (build version). The PlayerPrefs stopped working. It's just, like they never existed. Saving between Scenes does not work. Back in the Unity Editor, everything works. But why?

Hope somebody can help me, so I can play my game outside the editor 💀.

Kind regards.


Ok, restarted unity, and now I am getting an error, the game in and outside Unity malfunctions now the same. But why (and why tf did it work like a charm before I restarted and Unity recognized the error)? Please help.

FormatException: Input string was not in a correct format. System.Number.StringToNumber (System.String str, System.Globalization.NumberStyles options, System.Number+NumberBuffer& number, System.Globalization.NumberFormatInfo info, System.Boolean parseDecimal) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Number.ParseInt32 (System.String s, System.Globalization.NumberStyles style, System.Globalization.NumberFormatInfo info) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Int32.Parse (System.String s) (at <695d1cc93cca45069c528c15c9fdd749>:0) UI_Inventory.RefreshInventoryItemsNewWorld () (at Assets/SinglePlayer/Scripts/Inventory/UI_Inventory.cs:123) UI_Inventory.Start () (at Assets/SinglePlayer/Scripts/Inventory/UI_Inventory.cs:24)


Here is the script I save in:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using CodeMonkey.Utils;
    using TMPro;
    
    public class UI_Inventory : MonoBehaviour
    {
        private Inventory inventory;
        private Transform itemSlotContainer;
        private Transform itemSlotTemplate;
        private PlayerController player;
    
        private void Awake() {
            itemSlotContainer = transform.Find("itemSlotContainer");
            itemSlotTemplate = itemSlotContainer.Find("itemSlotTemplate");
        }
    
        private void Start()
        {
            RefreshInventoryItemsNewWorld();
        }
    
        public void SetPlayer(PlayerController player)
        {
            this.player = player;
        }
    
        public void SetInventory(Inventory inventory) 
        {
            this.inventory = inventory;
    
            inventory.OnItemListChanged += Inventory_OnItemListChanged;
    
            RefreshInventoryItems();
        }
    
        private void Inventory_OnItemListChanged(object sender, System.EventArgs e)
        {
            RefreshInventoryItems();
        }
    
        private void RefreshInventoryItems()
        {
            foreach (Transform child in itemSlotContainer)
            {
                if (child == itemSlotTemplate) continue;
                Destroy(child.gameObject);
            }
    
            int x = 0;
            int y = 0;
            float itemSlotCellSize = 90f;
    
            foreach (Item item in inventory.GetItemList())
            {
    
                RectTransform itemSlotRectTransform = Instantiate(itemSlotTemplate, itemSlotContainer).GetComponent<RectTransform>();
                itemSlotRectTransform.gameObject.SetActive(true);
    
                itemSlotRectTransform.GetComponent<Button_UI>().ClickFunc = () => 
                {
                    inventory.UseItem(item);
                };
    
                itemSlotRectTransform.GetComponent<Button_UI>().MouseRightClickFunc = () => 
                {
                    Item duplicateItem = new Item { itemType = item.itemType, amount = item.amount };
                    inventory.RemoveItem(item);
                    ItemWorld.DropItem(player.GetPosition(), duplicateItem);
                };
    
                itemSlotRectTransform.anchoredPosition = new Vector2(x * itemSlotCellSize, y * itemSlotCellSize);
                Image image = itemSlotRectTransform.Find("image").GetComponent<Image>();
                image.sprite = item.GetSprite();
    
                TextMeshProUGUI uiText = itemSlotRectTransform.Find("text").GetComponent<TextMeshProUGUI>();
                if (item.amount > 1)
                {
                    uiText.SetText(item.amount.ToString());
    
                    // sets player pref
                    PlayerPrefs.SetString(item.itemType.ToString(), item.amount.ToString());
    
                    PlayerPrefs.Save();
                } else {
                    uiText.SetText("");
                }
    
                x++;
                if (x > 4) {
                    x = 0;
                    y++;
                }
    
            }
            
        }
    
        private void RefreshInventoryItemsNewWorld()
        {
            foreach (Transform child in itemSlotContainer)
            {
                if (child == itemSlotTemplate) continue;
                Destroy(child.gameObject);
            }
    
            int x = 0;
            int y = 0;
            float itemSlotCellSize = 90f;
    
            foreach (Item item in inventory.GetItemList())
            {
                item.amount = int.Parse(PlayerPrefs.GetString(item.itemType.ToString()));
    
                RectTransform itemSlotRectTransform = Instantiate(itemSlotTemplate, itemSlotContainer).GetComponent<RectTransform>();
                itemSlotRectTransform.gameObject.SetActive(true);
    
                itemSlotRectTransform.GetComponent<Button_UI>().ClickFunc = () => 
                {
                    inventory.UseItem(item);
                };
    
                itemSlotRectTransform.GetComponent<Button_UI>().MouseRightClickFunc = () => 
                {
                    Item duplicateItem = new Item { itemType = item.itemType, amount = item.amount };
                    inventory.RemoveItem(item);
                    ItemWorld.DropItem(player.GetPosition(), duplicateItem);
                };
    
                itemSlotRectTransform.anchoredPosition = new Vector2(x * itemSlotCellSize, y * itemSlotCellSize);
                Image image = itemSlotRectTransform.Find("image").GetComponent<Image>();
                image.sprite = item.GetSprite();
    
                TextMeshProUGUI uiText = itemSlotRectTransform.Find("text").GetComponent<TextMeshProUGUI>();
                if (item.amount > 1)
                {
                    uiText.SetText(item.amount.ToString());
    
                    // sets player pref
                    PlayerPrefs.SetString(item.itemType.ToString(), item.amount.ToString());
    
                    PlayerPrefs.Save();
    
                } else {
                    uiText.SetText("");
                }
    
                x++;
                if (x > 4) {
                    x = 0;
                    y++;
                } 
            }
        }
    }
0

1 Answer 1

2

It's just, like they never existed.

Well, they don't. PlayerPrefs are device specific and also stored differently between the Editor and a built version of your project.


You are doing

item.amount = int.Parse(PlayerPrefs.GetString(item.itemType.ToString()));

however, if it is a new build / your PlayerPrefs non existent for whatever reason then

PlayerPrefs.GetString(item.itemType.ToString())

will return "" which makes

int.Parse("")

throw the exception.

In general you would rather

  • either provide a fallback value

    PlayerPrefs.GetString(item.itemType.ToString(), "0")
    

    which means if the according key does not exist in PlayerPrefs it will use "0" as fallback rather then returning the default ""

  • use int.TryParse instead to not get a exception but use a fallback value e.g.

     if(!int.TryParse(PlayerPrefs.GetString(item.itemType.ToString()), out item.amount)
     {
         item.amount = 0;
     }
    
  • combine both above just to be 100% sure


Or actually rather use PlayerPrefs.SetInt and PlayerPrefs.GetInt to begin with in order to not have to worry about the above at all.!

It anyway defaults to 0 and makes sure that what you store and retrieve there already is an int.

item.amount = PlayerPrefs.GetInt(item.itemType.ToString());
    

and of course accordingly also do

PlayerPrefs.SetInt(item.itemType.ToString(), item.amount);
Sign up to request clarification or add additional context in comments.

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.