Jump to content
ElectroMan

Como guardar las "variables del juego"

Recommended Posts

Buenas, estoy haciendo un rpg en 2D y querría que me aconsejaran donde o como guardar variables que almacenen información del tipo "el objeto de ID 0234 ya está cogido/no está cogido", "ya se ha hablado con X personaje 3 veces/aún no se ha hablado", "322 monstruos de tipo X eliminados".... Es decir serían una especie de variables globales a las que me gustaría acceder desde cualquier script para consultar algo, o por ejemplo cuando cargo una escena con una casa, consultar si el cofre que hay allí se ha abierto ya o no. Serían la mayoría variables booleanas pero también me gustaría guardar numéricas para poder consultar el nº de monstruos matados y cosas así. Creo que también me sería útil a la hora de implementar el sistema de quests, aunque aún no me he metido a fondo con él...

 

He estado probando con diccionarios cuya clave era el objeto/personaje y true o false en función de si ya se ha cogido/hablado con él, pero además de que esto solo me permite usar un tipo de variable (booleana en este caso) no funcionaba bien porque creaba el diccionario siempre con los mismos valores al iniciar el juego y al cargar partida no conseguía que lo sustituyese por el diccionario con los valores actualizados y tampoco sabía muy bien donde poner o como hacer los métodos que comprueben una por una las entradas del diccionario para hacer X cosa según el valor porque me parecía muy poco eficiente meterlo en un Update() y que esté constantemente comprobando eso... En fin que espero que entendáis lo que quiero hacer a ver si me podéis orientar un poco. Gracias.

Edited by ElectroMan

Share this post


Link to post
Share on other sites

puedes usar playerprefs, una clase serializable o si quieres que solo se guarde en ejecucion y se pierdan al cerrar la aplicacion una clase estatica,

Share this post


Link to post
Share on other sites

Pero utiliza una clase, no una variable en el Dict. Probablemente una lista te será más sencillo y luego serializarla o lo que sea. Pero primero una clase

Share this post


Link to post
Share on other sites

Guardar/Leer los datos desde PlayerPrefs, o bien desde un .asset (mediante ScriptableObject) es una buena forma de hacer lo que buscas.

Share this post


Link to post
Share on other sites

La decepción que me he llevado cuando me di cuenta que no se puede serializar GameObject, llevaba medio código hecho :(

Share this post


Link to post
Share on other sites

La decepción que me he llevado cuando me di cuenta que no se puede serializar GameObject, llevaba medio código hecho :(

Ningún objeto de unity(clase o estructura) se encuentra serializada, ni Vector3, ni Quaternion, etc...

Tienes que crear tus propias clases serializadas  o guardar los datos uno a uno en forma de float, int, bool, string, ...

Yo creo que la mejor solucion es guardar los datos en un Dictionary<string, object> que puede ser serializado/deserializado fácilmente, de forma genérica para cualquier tipo de dato serializado o elemental tipo float, int, string, etc...

Esta sería la clase FileData que utiliza un Dictionary<string,object> para almacenar y registrar todos los datos:

using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;


public class FileData{	

	string file;
	Dictionary<string, object> Data;

	public FileData(string file){

		this.Data = new Dictionary<string, object>();
		this.file = file;

	}
	
	public void Set(string name, object data){

		if(Data.ContainsKey(name)) Data[name] = data;
		else Data.Add(name, data);
		
	}
	
	public void Remove(string name){
		
		Data.Remove(name);
		
	}
	
	public object Get(string name){
		
		if(Data.ContainsKey(name)) return Data[name];
		return null;
		
	}


	public bool Save(){ return Save(this.file); }
	public bool Save(string file){
		
		FileStream fs = new FileStream(file, FileMode.Create);		
		
		BinaryFormatter formatter = new BinaryFormatter();
		try 
		{
			formatter.Serialize(fs, Data);
		}
		catch (System.Runtime.Serialization.SerializationException e) 
		{
			UnityEngine.Debug.Log("Failed to serialize. Reason: " + e.Message);
			return false;
		}
		finally 
		{
			fs.Close();
		}

		return true;
		
	}

	public bool Load(){ return Load(this.file); }
	public bool Load(string file){

		if(!File.Exists(file)) return false;

		FileStream fs = new FileStream(file, FileMode.Open);

		try 
		{
			BinaryFormatter formatter = new BinaryFormatter();
			Data = (Dictionary<string,object>) formatter.Deserialize(fs);
		}
		catch (System.Runtime.Serialization.SerializationException e)
		{
			UnityEngine.Debug.Log("Failed to deserialize. Reason: " + e.Message);
			return false;
		}
		finally 
		{
			fs.Close();
		}

		return true;
		
	}

	public static FileData Create(string file){

		return new FileData(file);

	}

	public static FileData From(string file){

		FileData fileData = new FileData(file);
		fileData.Load();
		return fileData;

	}
	
}

 

Podemos crear un solo objeto FileData para almacenar todos los datos del juego, o varios archivos: uno para los actores, otro para el gui/inventario, o uno diferente para cada escena.

He creado dos funciones estáticas, una FileData.Create(file) para crear un registro/base de datos en blanco, y otra FileData.From(file) para cargar los datos del disco al inicio.

 

El script tipo Test:

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

	public bool save;


	//Definir nombres de registro GameDataFile
	const string posicion_x = "Player/posicion_x";
	const string posicion_y = "Player/posicion_y";
	const string posicion_z = "Player/posicion_z";
	const string rotacion_x = "Player/rotacion_x";
	const string rotacion_y = "Player/rotacion_y";
	const string rotacion_z = "Player/rotacion_z";
	const string puntuacion = "Player/Puntuacion";
	const string vidas      = "Player/vidas";

	//Definir nombres de registro GUI
	const string Equipamiento1 = "Player/Equipamiento/slot1";
	const string Equipamiento2 = "Player/Equipamiento/slot2";
	const string Equipamiento3 = "Player/Equipamiento/slot3";
	const string Equipamiento4 = "Player/Equipamiento/slot4";
	const string Inventario1 = "Player/Inventario/slot1";
	const string Inventario2 = "Player/Inventario/slot2";
	const string Inventario3 = "Player/Inventario/slot3";
	const string Inventario4 = "Player/Inventario/slot4";
	const string Inventario5 = "Player/Inventario/slot5";
	const string Inventario6 = "Player/Inventario/slot6";
	const string Inventario7 = "Player/Inventario/slot7";
	const string Inventario8 = "Player/Inventario/slot8";
	const string Inventario9 = "Player/Inventario/slot9";
	const string Inventario10 = "Player/Inventario/slot10";
	const string Inventario11 = "Player/Inventario/slot11";
	const string Inventario12 = "Player/Inventario/slot12";

	
	// Use this for initialization
	void Start () {
		
		FileData GameData = FileData.Create("GameDataFile");
		//FileData GUIData = FileData.Create("GUIDataFile");

		if(save){

			GameData.Set(puntuacion, 15367);
			GameData.Set(vidas, 3);
			GameData.Set(posicion_x,this.transform.position.x);
			GameData.Set(posicion_y,this.transform.position.y);
			GameData.Set(posicion_z,this.transform.position.z);
			GameData.Set(rotacion_x,this.transform.eulerAngles.x);
			GameData.Set(rotacion_y,this.transform.eulerAngles.y);
			GameData.Set(rotacion_z,this.transform.eulerAngles.z);

			//Los datos se pueden sobreescribir o modificar
			//GameData.Set(posicion_x,17.15f);
			
			if(GameData.Save()) Debug.Log("Datos guardados con exito");
			else Debug.Log("Error al guardar datos");

			//GUIData.Set(Equipamiento1,"");
			//GUIData.Set(Equipamiento2,"");
			//etc...

			
		} else {
			
			if(GameData.Load()){

				Debug.Log(puntuacion + ": " + (int)GameData.Get(puntuacion));
				Debug.Log(vidas + ": " + (int)GameData.Get(vidas));
				Debug.Log(posicion_x + ": " + (float)GameData.Get(posicion_x));
				Debug.Log(posicion_y + ": " + (float)GameData.Get(posicion_y));
				Debug.Log(posicion_z + ": " + (float)GameData.Get(posicion_z));
				Debug.Log(rotacion_x + ": " + (float)GameData.Get(rotacion_x));
				Debug.Log(rotacion_y + ": " + (float)GameData.Get(rotacion_y));
				Debug.Log(rotacion_z + ": " + (float)GameData.Get(rotacion_z));

			} else Debug.Log("Error al cargar datos");
			
		}
		
	}
}

 

Share this post


Link to post
Share on other sites

Ningún objeto de unity(clase o estructura) se encuentra serializada, ni Vector3, ni Quaternion, etc...

Tienes que crear tus propias clases serializadas  o guardar los datos uno a uno en forma de float, int, bool, string, ...

Yo creo que la mejor solucion es guardar los datos en un Dictionary<string, object> que puede ser serializado/deserializado fácilmente, de forma genérica para cualquier tipo de dato serializado o elemental tipo float, int, string, etc...

Esta sería la clase FileData que utiliza un Dictionary<string,object> para almacenar y registrar todos los datos:

using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;


public class FileData{	

	string file;
	Dictionary<string, object> Data;

	public FileData(string file){

		this.Data = new Dictionary<string, object>();
		this.file = file;

	}
	
	public void Set(string name, object data){

		if(Data.ContainsKey(name)) Data[name] = data;
		else Data.Add(name, data);
		
	}
	
	public void Remove(string name){
		
		Data.Remove(name);
		
	}
	
	public object Get(string name){
		
		if(Data.ContainsKey(name)) return Data[name];
		return null;
		
	}


	public bool Save(){ return Save(this.file); }
	public bool Save(string file){
		
		FileStream fs = new FileStream(file, FileMode.Create);		
		
		BinaryFormatter formatter = new BinaryFormatter();
		try 
		{
			formatter.Serialize(fs, Data);
		}
		catch (System.Runtime.Serialization.SerializationException e) 
		{
			UnityEngine.Debug.Log("Failed to serialize. Reason: " + e.Message);
			return false;
		}
		finally 
		{
			fs.Close();
		}

		return true;
		
	}

	public bool Load(){ return Load(this.file); }
	public bool Load(string file){

		if(!File.Exists(file)) return false;

		FileStream fs = new FileStream(file, FileMode.Open);

		try 
		{
			BinaryFormatter formatter = new BinaryFormatter();
			Data = (Dictionary<string,object>) formatter.Deserialize(fs);
		}
		catch (System.Runtime.Serialization.SerializationException e)
		{
			UnityEngine.Debug.Log("Failed to deserialize. Reason: " + e.Message);
			return false;
		}
		finally 
		{
			fs.Close();
		}

		return true;
		
	}

	public static FileData Create(string file){

		return new FileData(file);

	}

	public static FileData From(string file){

		FileData fileData = new FileData(file);
		fileData.Load();
		return fileData;

	}
	
}

 

Podemos crear un solo objeto FileData para almacenar todos los datos del juego, o varios archivos: uno para los actores, otro para el gui/inventario, o uno diferente para cada escena.

He creado dos funciones estáticas, una FileData.Create(file) para crear un registro/base de datos en blanco, y otra FileData.From(file) para cargar los datos del disco al inicio.

 

El script tipo Test:

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

	public bool save;


	//Definir nombres de registro GameDataFile
	const string posicion_x = "Player/posicion_x";
	const string posicion_y = "Player/posicion_y";
	const string posicion_z = "Player/posicion_z";
	const string rotacion_x = "Player/rotacion_x";
	const string rotacion_y = "Player/rotacion_y";
	const string rotacion_z = "Player/rotacion_z";
	const string puntuacion = "Player/Puntuacion";
	const string vidas      = "Player/vidas";

	//Definir nombres de registro GUI
	const string Equipamiento1 = "Player/Equipamiento/slot1";
	const string Equipamiento2 = "Player/Equipamiento/slot2";
	const string Equipamiento3 = "Player/Equipamiento/slot3";
	const string Equipamiento4 = "Player/Equipamiento/slot4";
	const string Inventario1 = "Player/Inventario/slot1";
	const string Inventario2 = "Player/Inventario/slot2";
	const string Inventario3 = "Player/Inventario/slot3";
	const string Inventario4 = "Player/Inventario/slot4";
	const string Inventario5 = "Player/Inventario/slot5";
	const string Inventario6 = "Player/Inventario/slot6";
	const string Inventario7 = "Player/Inventario/slot7";
	const string Inventario8 = "Player/Inventario/slot8";
	const string Inventario9 = "Player/Inventario/slot9";
	const string Inventario10 = "Player/Inventario/slot10";
	const string Inventario11 = "Player/Inventario/slot11";
	const string Inventario12 = "Player/Inventario/slot12";

	
	// Use this for initialization
	void Start () {
		
		FileData GameData = FileData.Create("GameDataFile");
		//FileData GUIData = FileData.Create("GUIDataFile");

		if(save){

			GameData.Set(puntuacion, 15367);
			GameData.Set(vidas, 3);
			GameData.Set(posicion_x,this.transform.position.x);
			GameData.Set(posicion_y,this.transform.position.y);
			GameData.Set(posicion_z,this.transform.position.z);
			GameData.Set(rotacion_x,this.transform.eulerAngles.x);
			GameData.Set(rotacion_y,this.transform.eulerAngles.y);
			GameData.Set(rotacion_z,this.transform.eulerAngles.z);

			//Los datos se pueden sobreescribir o modificar
			//GameData.Set(posicion_x,17.15f);
			
			if(GameData.Save()) Debug.Log("Datos guardados con exito");
			else Debug.Log("Error al guardar datos");

			//GUIData.Set(Equipamiento1,"");
			//GUIData.Set(Equipamiento2,"");
			//etc...

			
		} else {
			
			if(GameData.Load()){

				Debug.Log(puntuacion + ": " + (int)GameData.Get(puntuacion));
				Debug.Log(vidas + ": " + (int)GameData.Get(vidas));
				Debug.Log(posicion_x + ": " + (float)GameData.Get(posicion_x));
				Debug.Log(posicion_y + ": " + (float)GameData.Get(posicion_y));
				Debug.Log(posicion_z + ": " + (float)GameData.Get(posicion_z));
				Debug.Log(rotacion_x + ": " + (float)GameData.Get(rotacion_x));
				Debug.Log(rotacion_y + ": " + (float)GameData.Get(rotacion_y));
				Debug.Log(rotacion_z + ": " + (float)GameData.Get(rotacion_z));

			} else Debug.Log("Error al cargar datos");
			
		}
		
	}
}

 

UFF! muchísimas gracias. 

Share this post


Link to post
Share on other sites

UnitySpain © Todos los derechos reservados 2020
×
×
  • Create New...