Saving and Loading Issues Lists/SetActive/Etc
Hi everyone, I'm a bit new to coding. I'm working on some code, more particularly a save function on a 2D platformer. I've searched quite in depthly (If it's not a word I made it up) the questions on this forum and several others, even watched several videos, (I must admit I typically hate watching videos they're long and drawn out, but I've watched them!) and I haven't stumbled upon an answer that has helped me yet.
So, here I come to ask a question (I hardly ever ever - well, I've never signed up for a site just to ask a question I usually just tough it out). Tldr; I've searched and yet to have an answer to my saving problems. (or at least one I could get to work)
Okay, so I have a GameControl script. I guess the easiest thing would be to post it. THere's probably a lot wrong with it... Sorry it's so long.
using System.Collections;
using System.Collections.Generic;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEngine;
public class GameControl : MonoBehaviour {
public static GameControl control;
//Data to Save and Load
public int lives;
public int currentScore;
public int currentLevel;
public int currentCheckpointID;
//balloons collected
public List<string> bIdActive;
private PlayerMovement player;
public LevelManager levelManager;
private Balloon balloon;
// Use this for initialization
void Awake () {
//if this game object doesn't exist, create it or if it exists, make sure there is only one.
if (control == null) {
DontDestroyOnLoad (gameObject);
control = this;
}
else if (control != this) {
Destroy(gameObject);
}
//player and player position management
player = FindObjectOfType<PlayerMovement> ();
levelManager = FindObjectOfType<LevelManager> ();
//balloon management
balloon = FindObjectOfType<Balloon> ();
bIdActive = new List<string> ();
}//end awake
//uses this on everything but web server
public void Save(){
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Create (Application.persistentDataPath + "/playerInfo.dat");
PlayerData data = new PlayerData ();
data.lives = lives;
data.currentScore = currentScore;
data.currentLevel = currentLevel;
data.currentCheckpointID = currentCheckpointID;
data.bIdActive = bIdActive;
bf.Serialize (file, data);
file.Close ();
}
public void Load() {
if (File.Exists (Application.persistentDataPath + "/playerInfo.dat")) {
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Open (Application.persistentDataPath + "/playerInfo.dat", FileMode.Open);
PlayerData data = (PlayerData)bf.Deserialize (file);
file.Close ();
lives = data.lives;
currentScore = data.currentScore;
currentLevel = data.currentLevel;
currentCheckpointID = data.currentCheckpointID;
bIdActive = data.bIdActive;
}
//this is where load would do stuff
SceneManager.LoadScene (currentLevel);
if (PlayerMovement.pMovementHasStarted) {
levelManager.respawnPlayer ();
}
//setting balloons inactive on load
if (balloon.bScriptStarted == true) {
// if (bIdActive.Contains (1)) {
// if (balloon.bID == 1)
// balloon.gameObject.SetActive (false);
// }
if (bIdActive.Contains ("rballoon2")) {
if (balloon.bID == 2) {
balloon.gameObject.SetActive (false);
}
}
// if (bIdActive.Contains (3)) {
// if (balloon.bID == 3)
// balloon.gameObject.SetActive (false);
// }
}
}//end of load function
[Serializable]
//class AllData {
class PlayerData {
public int lives;
public int currentScore;
public int currentLevel;
public int currentCheckpointID;
public List<string> bIdActive;
}
}
//}
this script is connected to a balloon script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Balloon : MonoBehaviour {
public int bID;
public bool bScriptStarted;
// Use this for initialization
void Start () {
bScriptStarted = true;
}
// Update is called once per frame
void Update () {
}
//*****************Delete red Balloon // Assign Points// Add to Deleted List***********//
void OnTriggerEnter2D (Collider2D col)
{
if (gameObject.CompareTag ("rBalloon")) {
//Destroy (gameObject);
gameObject.SetActive (false);
ScoreManager.AddPoints (10);
if (bID == 2) {
GameControl.control.bIdActive.Add ("rballoon2");
Debug.Log (GameControl.control.bIdActive);
}
}
if (gameObject.CompareTag ("bBalloon")) {
//Destroy (gameObject);
gameObject.SetActive(false);
ScoreManager.AddPoints (5);
if (bID == 1) {
GameControl.control.bIdActive.Add("bballoon1");
Debug.Log (GameControl.control.bIdActive);
}
if (bID == 3) {
GameControl.control.bIdActive.Add("bballoon3");
Debug.Log (GameControl.control.bIdActive);
}
}
}
}
I get these errors running this code: "MissingReferenceException: The object of type 'Balloon' has been destroyed but you are still trying to access it." and the "The referenced script on this Behaviour is missing!" and "The referenced script on this Behaviour (Game Object 'balloonRed') is missing!"
I have a bool set on the balloon script to show the script has started; if the script starts then the balloons are located on the GameControl script, however, that doesn't seem to be working...
My problem is that when I collect all the balloons and I save and then load the game, the balloons come back. and don't reset to inactive. i've tried a few different ways but nothing seems to work. I'm assuming that my list isn't saving or being created properly? But with my lack of knowledge I'm not so sure what exactly is going wrong.
I know that there is a GUID function that would give me IDs but they reset on each load which is no good. So I just tried using the most basic stuff for now to try to wrap my head around how it should work...
I have made sure that each balloon does have an ID they are 1 2 and 3. The red balloon is 2; the blue balloons are 1 and 3. I didn't have the get tag for the blue balloon because it didn't work for the red balloon so it would have been pointless to add.
The problem could be with the balloons not getting set to inactive, but I'm not sure...
I've gone with set inactive instead of destroying because destroying has been messing up well everything.
I hope whatever the issue is is really quick and easy so I don't take too much more of your time.... And if you've read all this you're really dedicated... Thank you.
Any help is appreciated.
Answer by DeadlyEssence · Apr 19, 2018 at 02:53 PM
I found out what was wrong with my script. Instead of trying to get the balloons to delete from the GameControl script on load, I just set them to be checked on the start of the balloon script.
In case it helps anyone here is the new balloon script (all reference to balloons was removed from the gamecontrol script aside from the list that is used to store the ID of the destroyed balloons.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Balloon : MonoBehaviour {
public float bID;
// Use this for initialization
void Start () {
//**** Balloon script starts on loa This deletes balloons already collected****//
if (GameControl.control.bIdActive.Contains ("rballoon2")) {
if (bID == 2) {
gameObject.SetActive (false);
}
}
if (GameControl.control.bIdActive.Contains ("bballoon1")) {
if (bID == 1) {
gameObject.SetActive (false);
}
}
if (GameControl.control.bIdActive.Contains ("bballoon3")) {
if (bID == 3) {
gameObject.SetActive (false);
}
}
}//end of start
// Update is called once per frame
void Update () {
}
//*****************Delete red Balloon Assign Points***********//
void OnTriggerEnter2D (Collider2D col)
{
if (gameObject.CompareTag ("rBalloon")) {
gameObject.SetActive(false);
ScoreManager.AddPoints (10);
if (bID == 2) {
GameControl.control.bIdActive.Add ("rballoon2");
}
}
if (gameObject.CompareTag ("bBalloon")) {
gameObject.SetActive(false);
ScoreManager.AddPoints (5);
if (bID == 1) {
GameControl.control.bIdActive.Add("bballoon1");
}
if (bID == 3) {
GameControl.control.bIdActive.Add("bballoon3");
}
}
}
}