Reputation: 11335
I have two scene : Main Menu, Game On the Main Menu I have also a two buttons : Save,Load
And two scripts :
Save System :
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public static class SaveSystem
{
public static void SavePlayer(Player player)
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/player.bin";
FileStream stream = new FileStream(path, FileMode.Create);
PlayerData data = new PlayerData(player);
formatter.Serialize(stream, data);
stream.Close();
}
public static PlayerData LoadPlayer()
{
string path = Application.persistentDataPath + "/player.bin";
if(File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
PlayerData data = formatter.Deserialize(stream) as PlayerData;
stream.Close();
return data;
}
else
{
Debug.LogError("Save file not found in " + path);
return null;
}
}
}
And Player :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public void SavePlayer()
{
SaveSystem.SavePlayer(this);
}
public void LoadPlayer()
{
PlayerData data = SaveSystem.LoadPlayer();
Vector3 position;
position.x = data.position[0];
position.y = data.position[1];
position.z = data.position[2];
transform.position = position;
}
}
The Player script is attached to the Player in the Game scene but now I can't call or get access to the SavePlayer and LoadPlayer from the two buttons in the On Click events.
And another problem is that the Game scene is not all the time in the Hierarchy the Game scene is loaded when I click the Play button and then the Main Menu scene is not loaded and when I hit the escape key it's loading the Main Menu scene but then the Game scene is not loaded.
So I wonder how should I and how can I make a reference between the buttons Save/Load and the functions SavePlayer/LoadPLayer ?
Upvotes: 0
Views: 102
Reputation: 90789
After we cleared out that your two scenes are actually not loaded at the same time I would use another approach.
You already have a static
class for your loading process. Either there or in a second one you could simply store the player data meanwhile still in the MainMenu. Then the player loads this data on start.
For the active loading and saving from within the game scene you could have another button for the saving.
Something like
public static class SaveSystem
{
public static PlayerData Data;
// Without a parameter serialize the values from the current Data
// which will be updated by the player
public static void SavePlayer()
{
WriteFile(Data);
}
public static void SavePlayer(Player player)
{
var data = new PlayerData(player);
WriteFile(data);
}
private static void WriteFile(PlayerData data)
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/player.bin";
FileStream stream = new FileStream(path, FileMode.Create);
formatter.Serialize(stream, data);
stream.Close();
}
public static PlayerData LoadPlayer()
{
string path = Application.persistentDataPath + "/player.bin";
if(File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
Data = formatter.Deserialize(stream) as PlayerData;
stream.Close();
return Data;
}
else
{
Debug.LogError("Save file not found in " + path);
return null;
}
}
}
Then from the menu
public class MenuButtons : MonoBehaviour
{
public void Load()
{
// Only reads the save file into the SaveSystem.Data
SaveSystem.LoadPlayer();
}
public void Save()
{
// Only write SaveSystem.Data to the file
SaveSystem.SavePlayer();
}
}
Now in the game scene on the player
public class Player : MonoBehaviour
{
// Load the player values on startup from SaveSystem.Data
private void Awake ()
{
var data = SaveSystem.Data;
if(data == null) return;
Vector3 position;
position.x = data.position[0];
position.y = data.position[1];
position.z = data.position[2];
transform.position = position;
}
// Now it is up to you when and how often you want the player to save its data
// I would do it e.g. in OnDestroy
// so everytime the scene is changed
private void OnDestroy ()
{
// Only populates the SaveSystem.Data
// without necessarily writing the file
SaveSystem.Data = new PlayerData(this);
}
}
Upvotes: 1