Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by alessio1918m · May 31 at 06:40 AM · singletonnull reference exceptionwhy

Singleton reference suddenly becomes null, why?


This used to work consistently for a long time until it randomly started getting a NullReferenceExeption for my singleton class, i have been trying to understand why but it makes no sense to me, it looks like it's triggering an OnApplicationPause method before Awake methods but i don't get it...


alt text


 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using BreakInfinity;
 public class MineSpawner : MonoBehaviour
 {
     [SerializeField] private int maxMinesAtOnce;
     [SerializeField] private float mineSpawnInterval;
     [SerializeField] private float spawnHeight;
 
     [SerializeField] private float[] chance;
     [SerializeField] private GameObject[] mineTypes;
 
     [SerializeField] private Transform mineSlotsParent;
 
     private DataController dataC;
 
     private void Start()
     {
         dataC = DataController.Instance;
 
         SpawnSavedMines();
 
         InvokeRepeating("SpawnMine", 0f, mineSpawnInterval);
     }
 
     void SpawnSavedMines()
     {
         for (int i = 0; i < dataC.minesParent.Count; i++)
         {
             GameObject newMine = Instantiate(mineTypes[dataC.minesType[i]], mineSlotsParent.GetChild(dataC.minesParent[i]));
             newMine.gameObject.GetComponent<MineLogic>().maxHitPoints = dataC.minesMaxHitPoints[i];
             newMine.gameObject.GetComponent<MineLogic>().mineType = dataC.minesType[i];
         }
 
         CheckCurrentMinesAmount();
     }
 
     void SpawnMine()
     {
         CheckCurrentMinesAmount();
 
         if (PlayerPrefs.GetInt("CurrentMines") < maxMinesAtOnce)
         {
             float percentageCap = 0f;
 
             for (int i = 0; i < chance.Length; i++) // gets the sum of total percentages
             {
                 percentageCap += chance[i];
             }
 
             float tempChance = 0f; // initializes percentage checking
 
             float roll = Random.Range(0f, percentageCap); // random number roll for percentage
 
             for (int i = 0; i < mineTypes.Length; i++)
             {
                 if (roll >= tempChance && roll < tempChance + chance[i])
                 {
                     GameObject newMine = Instantiate(mineTypes[i], GetRandomFreeChild());
                     newMine.transform.position += new Vector3(0, spawnHeight, 0);
                     newMine.transform.eulerAngles = new Vector3(0,Random.Range(0,360),0);
 
                     switch (newMine.tag)
                     {
                         case "Copper":
                             newMine.GetComponent<MineLogic>().maxHitPoints = BigDouble.Round(dataC.copperOreHealth +
                                 dataC.copperOreHealth * Random.Range(0,0.1f));
 
                             break;
                         case "Iron":
                             newMine.GetComponent<MineLogic>().maxHitPoints = BigDouble.Round(dataC.ironOreHealth +
                                 dataC.ironOreHealth * Random.Range(0, 0.1f));
                             break;
                     }
                     newMine.GetComponent<MineLogic>().mineType = i;
                 }
 
                 tempChance += chance[i]; // add new percentage to check before looping again
             }
 
         }
     }
 
     Transform GetRandomFreeChild()
     {
         int randomParentNum;
         do
         {
             randomParentNum = Random.Range(0, mineSlotsParent.childCount);
 
         } while (mineSlotsParent.GetChild(randomParentNum).childCount != 0);
 
         return mineSlotsParent.GetChild(randomParentNum);
     }
 
     void CheckCurrentMinesAmount()
     {
         int count = 0;
         foreach (Transform childs in mineSlotsParent)
         {
             if (childs.childCount != 0)
             {
                 count++;
             }
         }
         PlayerPrefs.SetInt("CurrentMines", count);
     }
     private void SaveMines()
     {
         if (dataC == null) Debug.Log("dataC is null"); //debug
 
         dataC.minesParent.Clear();
         dataC.minesMaxHitPoints.Clear();
         dataC.minesType.Clear();
 
         for (int i = 0; i < mineSlotsParent.childCount; i++)
         {
             if (mineSlotsParent.GetChild(i).childCount != 0)
             {
                 dataC.minesParent.Add(i);
                 dataC.minesMaxHitPoints.Add(mineSlotsParent.GetChild(i).GetChild(0).GetComponent<MineLogic>().maxHitPoints);
                 dataC.minesType.Add(mineSlotsParent.GetChild(i).GetChild(0).GetComponent<MineLogic>().mineType);
             }
         }
 
         CheckCurrentMinesAmount();
         dataC.SaveMineObjects();
     }
     private void OnApplicationQuit()
     {
         SaveMines();
         Debug.Log("MineSpawner OAQ triggered");
     }
     private void OnApplicationPause(bool pause)
     {
         SaveMines();
         Debug.Log("MineSpawner OAP triggered");
     }
 }
 

The singleton DataController class:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using BreakInfinity;
 using TMPro;
 
 public class DataController : MonoBehaviour
 {
     public float basePrice, baseProd, baseSpeed, priceMult, prodMult, speedMult; //for prototype
 
     [SerializeField] private float saveCycleSeconds;
 
     [SerializeField] private string saveFileName;
 
     [SerializeField] private TMP_Text smallInvCopper;
     [SerializeField] private TMP_Text smallInvIron;
 
 
     Data data;
     MineData mineData;
     UpgradeData upgradeData;
     MineObjects mineObjects;
     Init init;
 
     public BigDouble coins;
 
     public BigDouble copper;
     public BigDouble iron;
 
     public BigDouble damage;
 
     public BigDouble copperOreHealth;
     public BigDouble ironOreHealth;
 
     public BigDouble copperPerSecond;
     public BigDouble ironPerSecond;
     ///////
     public int copperMineLevel;
     public int ironMineLevel;
 
     public BigDouble copperMineProd;
     public BigDouble ironMineProd;
 
     public float copperMineRate;
     public float ironMineRate;
 
     public BigDouble copperUpgradePrice;
     public BigDouble ironUpgradePrice;
     ////////
     public float copperPriceMultiplier;
     public float ironPriceMultiplier;
 
     public byte copperPriceULevel;
     public byte ironPriceULevel;
 
     private float copperTimer;
     private float ironTimer;
     ////////
     public List<int> minesParent;
     public List<BigDouble> minesMaxHitPoints;
     public List<int> minesType;
     ///////
 
     #region singleton stuff
     public static DataController Instance
     {
         get
         {
             if (_instance == null)
             {
                 Debug.LogWarning("DataController is null");
                 _instance = FindObjectOfType(typeof(DataController)) as DataController;
                 if (_instance == null) Debug.LogError("DataController still null after fixing attempt :(");
                 Debug.Log("DataController now fixed");
             }
             
             return _instance;
         }
         set
         {
             _instance = value;
         }
     }
     private static DataController _instance;
     #endregion
 
     private void Awake()
     {
         _instance = this;
 
         data = SavingSystem.SaveExists(saveFileName) ? SavingSystem.LoadData<Data>(saveFileName) : new Data();
         mineData = SavingSystem.SaveExists(saveFileName + "MineData") ? SavingSystem.LoadData<MineData>(saveFileName + "MineData") : new MineData();
         upgradeData = SavingSystem.SaveExists(saveFileName + "UpgradeData") ? SavingSystem.LoadData<UpgradeData>(saveFileName + "UpgradeData") : new UpgradeData();
         mineObjects = SavingSystem.SaveExists(saveFileName + "MineObjects") ? SavingSystem.LoadData<MineObjects>(saveFileName + "MineObjects") : new MineObjects();
         init = SavingSystem.SaveExists(saveFileName + "Init") ? SavingSystem.LoadData<Init>(saveFileName + "Init") : new Init();
 
         Load();
         UpdateOPS();
     }
 
     private void Start()
     {
         InvokeRepeating("AutoSaveCycle", saveCycleSeconds, saveCycleSeconds);
 
         copperTimer = Time.time;
         ironTimer = Time.time;
 
         
 
     }
 
     private void Update()
     {
         //copper += copperPerSecond * Time.deltaTime;
         //iron += ironPerSecond * Time.deltaTime;
 
         UpdateSmallInv();
 
         if (Time.time > copperTimer)
         {
             copper += copperMineProd;
             smallInvCopper.text = Utils.IdleGameNumberBigDouble(copper);
             copperTimer += copperMineRate;
         }
         if (Time.time > ironTimer)
         {
             iron += ironMineProd;
             smallInvIron.text = Utils.IdleGameNumberBigDouble(iron);
             ironTimer += ironMineRate;
         }
 
     }
     public void UpdateOPS() //
     {
         copperUpgradePrice = basePrice * BigDouble.Pow(priceMult, copperMineLevel);
 
         copperMineProd = baseProd * BigDouble.Pow(prodMult, copperMineLevel);
         copperMineRate = baseSpeed / Mathf.Pow(speedMult, copperMineLevel);
 
         if (copperMineRate > 0) copperPerSecond = copperMineProd / copperMineRate;
         if (ironMineRate > 0) ironPerSecond = ironMineProd / ironMineRate;
 
         SaveMineData();
     }
     public void UpdateSmallInv()
     {
         smallInvCopper.text = Utils.IdleGameNumberBigDouble(copper);
         smallInvIron.text = Utils.IdleGameNumberBigDouble(iron);
     }
 
     void AutoSaveCycle()
     {
         InternalSave();
     }
     void OnApplicationPause()
     {
         InternalSave();
         SaveMineData();
         SaveUpgradeData();
         //SaveMineObjects();
         Debug.Log("OnApplicationPause Triggered!", gameObject);
     }
     void OnApplicationQuit()
     {
         InternalSave();
         SaveMineData();
         SaveUpgradeData();
         //SaveMineObjects();
         Debug.Log("OnApplicationQuit Triggered!", gameObject);
     }
 
     void Load()
     {
         coins = data.coins;
 
         copper = data.copper;
         iron = data.iron;
 
         damage = data.damage;
 
         copperOreHealth = data.copperOreHealth;
         ironOreHealth = data.ironOreHealth;
 
         copperPerSecond = data.copperPerSecond;
         ironPerSecond = data.ironPerSecond;
         ////////////////////////////
         copperMineLevel = mineData.copperMineLevel;
         ironMineLevel = mineData.ironMineLevel;
 
         copperMineProd = mineData.copperMineProd;
         ironMineProd = mineData.ironMineProd;
 
         copperMineRate = mineData.copperMineRate;
         ironMineRate = mineData.ironMineRate;
 
         copperUpgradePrice = mineData.copperUpgradePrice;
         ironUpgradePrice = mineData.ironUpgradePrice;
         ////////////////////////////
         copperPriceMultiplier = upgradeData.copperPriceMultiplier;
         ironPriceMultiplier = upgradeData.ironPriceMultiplier;
 
         copperPriceULevel = upgradeData.copperPriceULevel;
         ironPriceULevel = upgradeData.ironPriceULevel;
         ///////////////////////////
         minesParent = mineObjects.minesParent;
         minesMaxHitPoints = mineObjects.minesMaxHitPoints;
         minesType = mineObjects.minesType;
     }
     public void InternalSave()
     {
         data.coins = coins;
 
         data.copper = copper;
         data.iron = iron;
 
         data.damage = damage;
 
         data.copperOreHealth = copperOreHealth;
         data.ironOreHealth = ironOreHealth;
 
         data.copperPerSecond = copperPerSecond;
         data.ironPerSecond = ironPerSecond;
 
         SavingSystem.SaveData(data, saveFileName);
     }
     public void SaveMineData()
     {
         mineData.copperMineLevel = copperMineLevel;
         mineData.ironMineLevel = ironMineLevel;
 
         mineData.copperMineProd = copperMineProd;
         mineData.ironMineProd = ironMineProd;
 
         mineData.copperMineRate = copperMineRate;
         mineData.ironMineRate = ironMineRate;
 
         mineData.copperUpgradePrice = copperUpgradePrice;
         mineData.ironUpgradePrice = ironUpgradePrice;
          
         SavingSystem.SaveData(mineData, saveFileName + "MineData");
     }
     public void SaveUpgradeData()
     {
         upgradeData.copperPriceMultiplier = copperPriceMultiplier;
         upgradeData.ironPriceMultiplier = ironPriceMultiplier;
 
         upgradeData.copperPriceULevel = copperPriceULevel;
         upgradeData.ironPriceULevel = ironPriceULevel;
 
         SavingSystem.SaveData(upgradeData, saveFileName + "UpgradeData");
     }
     public void SaveMineObjects()
     {
         mineObjects.minesParent = minesParent;
         mineObjects.minesMaxHitPoints = minesMaxHitPoints;
         mineObjects.minesType = minesType;
 
         SavingSystem.SaveData(mineObjects, saveFileName + "MineObjects");
 
         Debug.Log("mine objects saved!");
     }
 }


aa.png (33.2 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by rh_galaxy · Jun 01 at 03:41 AM

Try adding

 DontDestroyOnLoad(gameObject);

To the Awake() of DataController.

Also you can try DataController.Instance instead of dataC in SaveMines() just to get some more info about this (does the DataController Instance exist at all).

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image alessio1918m · Jun 01 at 07:36 AM 0
Share

Thanks for the insight, i tried and DataController.instance existed, also added the DontDestroyOnLoad to the class, to fix the problem I ended up adding if (dataC == null) return; at the beginning of the SaveMines function so the code doesn't get executed before assigning the instance to dataC. Turns out I didn't really know how OnApplicationPause works, i was supposed to add if (pause == true) { // code } because otherwise it gets executed before awake methods.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

185 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do switch scene with singleton pattern unity3d C# 2 Answers

Referencing monobehaviour singleton from a non-monobehaviour class? 1 Answer

GameObject only spawning 60% of the time (c#) 1 Answer

Null Reference Exeption harmless? 2 Answers

NullReference Exeption thrown even when checked against 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges