- Home /
non-static Variable in script on multiple gameObjects reset. Why?
I have a script that controls multiple buttons. The buttons are for selecting skins in a 2d game. I have a variable called SkinStatus, which shows if the specific skin is bought, not bought, or equipped. Right after running Load(), which loads in all of the statuses for all of the skins from JSON, the program sets the SkinStatus variable, but it just becomes 0 after the function and functions called from it finish. Since the script is on multiple objects, I need each one to have its own SkinStatus value. Thanks for any help! Please ask questions if you have any!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using TMPro;
public class SkinButton : MonoBehaviour
{
public GameObject controller;
private ShopController controllerScript;
//ref to the NotEnoughCoinsScreen
public GameObject NotEnoughCoinsScreen;
//ref to child text
private GameObject ButtonText;
private TextMeshProUGUI ButtonTextBox;
public int SkinStatus;
public string statusId;
public string ID;
private int SkinPrice;
private int currentCoins;
private int justEquipped;
SkinPrices skinPrices = new SkinPrices{
Skin1 = 0,
Skin2 = 10,
};
void Start()
{
//Use Transform.Find to just get the child ButtonText, not the other ones.
ButtonText = transform.Find("ButtonText").gameObject;
ButtonTextBox = ButtonText.GetComponent<TextMeshProUGUI>();
controllerScript = controller.GetComponent<ShopController>();
justEquipped = 0;
//This is to get the skin's current status (Not bought (1), bought(2), equipped(3)) and
//make the button say the correct text.
Load();
}
public void SetButtonText(int SkinStatus){
if (SkinStatus == 1){
ButtonTextBox.text = "Buy";
ButtonTextBox.fontSize = 50;
}else if (SkinStatus == 2){
ButtonTextBox.text = "Equip";
ButtonTextBox.fontSize = 50;
}else if (SkinStatus == 3) {
ButtonTextBox.text = "Equipped";
ButtonTextBox.fontSize = 30;
}
}
public void OnClick()
{
//DEBUG!!!! REMOVE LINE BELOW
PlayerPrefs.SetInt("coins",10);
Debug.Log(SkinStatus);
//Really weird bug where the SkinStatus will be immideatly scrapped after running Load()
//Maybe from running mulitple gameObjects off of same script?
//Runs Load() right before checking SkinStatus so we have accurate information.
Load();
Debug.Log(SkinStatus);
if (SkinStatus == 1){
//Uses reflection, to find the correct value in the SkinPrices object.
//As mentioned, expensive, but simple enough here.
SkinPrice = Convert.ToInt32(skinPrices.GetType().GetField(ID).GetValue(skinPrices));
currentCoins = PlayerPrefs.GetInt("coins");
if (currentCoins >= SkinPrice){
//set coins to coins amount minus the skin price and save it. Get it again to get
//updated currentCoins amount
PlayerPrefs.SetInt("coins",currentCoins - SkinPrice);
currentCoins = PlayerPrefs.GetInt("coins");
controllerScript.UpdateSave(statusId,2);
ButtonTextBox.text = "Equip";
ButtonTextBox.fontSize = 50;
}else{
NotEnoughCoinsScreen.SetActive(true);
}
}else if (SkinStatus == 2){
controllerScript.UpdateSave(statusId,3);
ButtonTextBox.text = "Equipped";
ButtonTextBox.fontSize = 30;
justEquipped = 1;
Debug.Log(justEquipped + ID);
}else if (SkinStatus == 3) {
}
}
public void Load(){
if(File.Exists(Application.persistentDataPath + "/SkinSave.json")) {
string saveString = File.ReadAllText(Application.persistentDataPath + "/SkinSave.json");
SaveObject saveObject = JsonUtility.FromJson<SaveObject>(saveString);
//Use reflection to find the correct property in the class. A bit slow,
//but good enough for now. It's not running mid-game or anything.
//Also convert the object into int
int SkinStatus = Convert.ToInt32(saveObject.GetType().GetField(statusId).GetValue(saveObject));
SetButtonText(SkinStatus);
Debug.Log(statusId+"->"+SkinStatus);
}else{
Debug.Log("Uh oh, no save file! From button");
//If this object is the default skin, set it as equipped
if (ID == "Skin1"){
SetButtonText(3);
SkinStatus = 3;
}else{
SetButtonText(1);
SkinStatus = 1;
}
}
}
public void CheckEquipped()
{
Load();
Debug.Log(justEquipped + ID);
if (SkinStatus == 3 && justEquipped == 0){
ButtonTextBox.text = "Equip";
ButtonTextBox.fontSize = 50;
}
}
private class SaveObject {
public int statusSkin1;
public int statusSkin2;
}
//Just a class that holds all of the prices. Uses Skin# as key
//so the manually inputted values match the prices.
private class SkinPrices {
public int Skin1;
public int Skin2;
}
}
Answer by Namey5 · Mar 21, 2020 at 01:28 AM
At line 114:
int SkinStatus = Convert.ToInt32(saveObject.GetType().GetField(statusId).GetValue(saveObject));
You don't actually write to the SkinStatus variable. Instead, you declare a local variable of the same name and use that, meaning the script will probably still look like it functions as normal, but you won't actually end up storing the status. If you want to do that, just remove the 'int' type before the assignment.
Aah, I did a dumb. Thanks a lot for catching that! I thought it was a different problem altogether.