-1

I am at begginner level with unity.

I have Load() function that goes off in OnApplicationPause(false). It works fine if I block the screen or minimalise app, and come back to it. However, when I kill it, I get error and the data doesnt get loaded.

Below is the script attached to the GameObject "SaveManager"

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

public class SaveManager : MonoBehaviour
{
    public GameObject ZwierzetaGroup;
    public GameObject JedzeniaGroup;
    public GameObject PrzedmiotyGroup;

    public List<GameObject> zwierzeta_sprites;
    public List<GameObject> jedzenia_sprites;
    public List<GameObject> przedmioty_sprites;

    public static DateTime oldDate;

    Camera mainCamera;
    public SaveState saveState;


    void Start()
    {
        mainCamera = Camera.main;
        FillArrays();
    }


    public void Save()
    {
        Debug.Log("Saving.");

        SaveSpriteArray("zwierze", zwierzeta_sprites);
        SaveSpriteArray("przedmiot", przedmioty_sprites);
        SaveSpriteArray("jedzenie", jedzenia_sprites);

        PlayerPrefs.SetInt("pieniazki", saveState.GetPieniazki());

        PlayerPrefs.SetInt("HayAmount", saveState.GetHayAmount());
        PlayerPrefs.SetInt("HayMax", saveState.GetHayMax());
        PlayerPrefs.SetInt("FruitAmount", saveState.GetFruitAmount());
        PlayerPrefs.SetInt("FruitMax", saveState.GetFruitMax());


        //time:
        PlayerPrefs.SetString("sysString", System.DateTime.Now.ToBinary().ToString());

        PlayerPrefs.SetInt("First", 1);
    }

    public void SaveSpriteArray(string saveName, List<GameObject> sprites)
    {
        
        for (int i = 0; i < sprites.Count; i++)
        {
            if (sprites[i].activeSelf)
            {
                PlayerPrefs.SetInt(saveName + i, 1);
            }
            else
            {
                PlayerPrefs.SetInt(saveName + i, 0);
            }

        }

    }

    public void Load()
    {
        Debug.Log("Loading.");

        //wczytanie czasu:
        long temp = Convert.ToInt64(PlayerPrefs.GetString("sysString"));
        oldDate = DateTime.FromBinary(temp);
        Debug.Log("oldDate: " + oldDate);

        //wczytywanie aktywnych sprite'ow
        LoadSpriteArray("zwierze", zwierzeta_sprites);
        LoadSpriteArray("przedmiot", przedmioty_sprites);
        LoadSpriteArray("jedzenie", jedzenia_sprites);

        saveState.SetPieniazki(PlayerPrefs.GetInt("pieniazki"));

        saveState.SetHayAmount(PlayerPrefs.GetInt("HayAmount"));
        saveState.SetHayMax(PlayerPrefs.GetInt("HayMax"));
        saveState.SetFruitAmount(PlayerPrefs.GetInt("FruitAmount"));
        saveState.SetFruitMax(PlayerPrefs.GetInt("FruitMax"));


        mainCamera.GetComponent<UpdateMoney>().MoneyUpdate();
    }

    public void LoadSpriteArray(string saveName, List<GameObject> sprites)
    {

        for (int i = 0; i < sprites.Count; i++)
        {
            if (PlayerPrefs.GetInt(saveName + i) == 1)
            {
                sprites[i].SetActive(true);
            }
            else
            {
                sprites[i].SetActive(false);
            }

        }

    }

    private void FillArrays()
    {
        //find children
        foreach (Transform child in ZwierzetaGroup.transform)
        {
            zwierzeta_sprites.Add(child.gameObject);
        }

        foreach (Transform child in PrzedmiotyGroup.transform)
        {
            przedmioty_sprites.Add(child.gameObject);
        }

        foreach (Transform child in JedzeniaGroup.transform)
        {
            jedzenia_sprites.Add(child.gameObject);
        }
    }
}

Below is a chunk of script attached to the main camera (probably a mistake). SaveManager GameObject with Script is attached to this one in inspector. This script is pretty big, so I'll skip the parts that I don't find relevant.

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

public class ManageEncouters: MonoBehaviour
{
    DateTime currentDate;


    public int First;

    public SaveState saveState;
    public SaveManager saveManager;

    public HayBar hayBar;
    public FruitBar fruitBar;

    public GameObject[] jedzenia_sprites;

    void Start()
    {

    }

    void OnApplicationPause(bool pauseStatus)
    {
        if (!pauseStatus)
        {
            currentDate = System.DateTime.Now;

            //Sprawdzanie czy jest to piersze uruchomienie gry (brak zapisu)
            First = PlayerPrefs.GetInt("First");
            if (First == 0)
            {
                Debug.Log("First time in app.");
                RandomiseAnimals();

                SaveManager.oldDate = currentDate;

                hayBar.SetHayMax(1);
                hayBar.SetHay(0);

                fruitBar.SetFruitMax(1);
                fruitBar.SetFruit(0);

                saveState.SetPieniazki(100);
                this.GetComponent<UpdateMoney>().MoneyUpdate();

            }
            else
            {
                Debug.Log("Not the first time in app.");
                saveManager.Load();

            }

            if (TimeInSeconds(currentDate, SaveManager.oldDate) > 12)
            {
                Debug.Log("It's been more than 12 seconds sience last time.");
                EatFood(currentDate, SaveManager.oldDate); 
                RandomiseAnimals();
            }
            else
            {

                Debug.Log("It's been less than 12 seconds sience last time.");
            }

        }
        if (pauseStatus)
        {
            saveManager.Save();
        }
    }

    private int TimeInSeconds(DateTime newD, DateTime oldD)
    {
        TimeSpan difference = newD.Subtract(oldD);

        int seconds = (int)difference.TotalSeconds;

        return seconds;
    }
}

Below is the error I get, I don't know how to copy the text, so it's an Image. error screenschot: NullReferenceException: Object Reference not set to an instance of an object

Proppane
  • 11
  • 2
  • 1
    Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – BugFinder May 02 '21 at 18:44

1 Answers1

1

I'm pretty sure that what you have here is a timing issue.

OnApplicationPause

Note: MonoBehaviour.OnApplicationPause is called as a GameObject starts. The call is made after Awake. Each GameObject will cause this call to be made.

So to me this sounds like it might be called when your SaveManager is not yet initialized, in particular the mainCamera.

I think you could already solve the issue by moving the initialization into Awake instead

private void Awake()
{
    mainCamera = Camera.main;
    FillArrays();
}

In general my little thumb rule is

  • use Awake wherever possible. In particular initialize everything where you don't depend on other scripts (initialize fields, use GetComponent, etc)

  • use Start when you need other scripts to be initialized already (call methods on other components, collect and pass on instances of some prefabs spawned in Awake, etc)

This covers most of cases. Where this isn't enough you would need to bother with the execution order or use events.

derHugo
  • 83,094
  • 9
  • 75
  • 115