Jump to content
UnitySpain
Sign in to follow this  
Antonio

Solved - Salvar y Cargar listas de objeto dinámicas

Recommended Posts

Saludos, tengo este código para cargar y guardar. Funciona.

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

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

public class Serializer_Level : MonoBehaviour
{
    public GameObject player;

    void Start ()
    {
        Load ();
    }

    void Update ()
    {
        if (Input.GetKeyDown (KeyCode.S))
        {
            Save ();
        }
    }

    public void Save ()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/playerInfo.dat");

        SavedData data = new SavedData();
        data.x = player.transform.position.x;
        data.y = player.transform.position.y;
        data.z = player.transform.position.z;

        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);
            SavedData data = (SavedData)bf.Deserialize (file);
            file.Close();

            player.transform.position = new Vector3 (data.x, data.y, data.z);
        }
    }
}

[Serializable]
class SavedData
{
    public float x;
	public float y;
	public float z;
}

 

La cosa es que necesito ir más allá, yo lo que estoy haciendo es como una pequeña zona de decoración, hay un área, y el jugador puede poner, quitar, mover, rotar, los objetos en ella.

dd4oi9g-558f314c-a972-4e91-84c1-eb6f3025

 

 

Ahora lo que necesito es salvar la posición, rotación y número de identificación para una serie grande de objetos (No sólo la posición del jugador como tengo en el código). ¿Alguien sabe como hacer esto?


Estoy pensando en estructuras y rayándome un poco. ¿Quizás algo como esto?:

dd4oit6-0d969232-94ea-4106-90a8-0ec13dd0

Una lista vector con las zonas de construcción (los cuadrados) estas son fijas en el nivel, así que no tengo que salvar nada de ellas salvo una lista vector con los objetos que contienen. Después cada objeto de esa "sub-lista" podría tener la información del ID, la posición y la rotación.

Lo que no sé es como meter esa estructura de lista dinámica (vector, deque, list o como sea), en el archivo binario que tengo que crear. (He leído una sugerencia de crear varios archivos externos por cada GameObject, pero dado que es posible que haya muchos objetos construidos en el nivel, creo que sería impensable tener un archivo externo por cada GameObject. 

 

¿Alguna idea? O_ò

 

/---/EDIT
Asunto solucionado en post 2

Edited by Antonio

Share this post


Link to post
Share on other sites

Vale, creo que más o menos está funcionando.

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

using System.Linq;

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

public class Serializer_Level : MonoBehaviour
{
    public Transform ConstructionAreasContainer;

    void Start ()
    {
        
    }

    void Update ()
    {
        if (Input.GetKeyDown (KeyCode.S)) //Pulsa S para salvar
        {
            Save ();
        }
        if (Input.GetKeyDown (KeyCode.L)) //Pulsa L para cargar
        {
            Load ();
        }
    }

    public void Save ()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/playerInfo.dat");

        SavedData data = new SavedData(); //Solo 1

        int NumberOfAreas = ConstructionAreasContainer.childCount; //Cuantas areas hay?
        for (int area = 0; area < NumberOfAreas; area++)
        {
            data.ConstructionAreas.Add (new AreaObj ()); //La añadimos a los datos
            Transform CurrentArea = ConstructionAreasContainer.GetChild (area); //Para ahorrar un poco en el siguiente bucle.
            
            int NumberOfObjs = CurrentArea.childCount; //Cuantos objetos tiene ese area?
            for (int i = 0; i < NumberOfObjs; i++)
            {
                data.ConstructionAreas.Last().Objs.Add (new BuilderObj());//Crea el espacio y guarda todas los valores.
                data.ConstructionAreas.Last().Objs.Last().posx = CurrentArea.GetChild (i).position.x;
                data.ConstructionAreas.Last().Objs.Last().posy = CurrentArea.GetChild (i).position.y;
                data.ConstructionAreas.Last().Objs.Last().posz = CurrentArea.GetChild (i).position.z;
                print ("Objeto " + CurrentArea.GetChild (i) + "salvado con valores: " + data.ConstructionAreas.Last().Objs.Last().posx + ", " + data.ConstructionAreas.Last().Objs.Last().posy + "and " + data.ConstructionAreas.Last().Objs.Last().posz );
            }
            print ("En el area " + area);
        }

        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);
            SavedData data = (SavedData)bf.Deserialize (file);
            file.Close();

            int AreaIndex = 0;

            foreach (AreaObj area in data.ConstructionAreas)
            {//Ahora, en cada area, hay que rellenarla//actualizarla de objetos. Voy a actualizar de momento para probar las listas dinámicas.
                
                Transform CurrentArea = ConstructionAreasContainer.GetChild (AreaIndex);
                print ("En Area " + CurrentArea);
                int ObjIndex = 0;
                foreach (BuilderObj it in area.Objs)
                {
                    CurrentArea.GetChild(ObjIndex).position = new Vector3 (it.posx, it.posy,it.posz);
                    print ("El objeto " + CurrentArea.GetChild(ObjIndex) + "ha sido cargado con valores: " + it.posx + ", " + it.posy + "and " + it.posz);
                    ObjIndex ++;
                }
                AreaIndex ++;
            }
        }
    }
}

[Serializable]
class SavedData
{
    public List <AreaObj> ConstructionAreas = new List <AreaObj>();
}

[Serializable]
class AreaObj
{
    public List <BuilderObj> Objs = new List <BuilderObj>();
}

[Serializable]
class BuilderObj
{
    public float posx;
	public float posy;
	public float posz;
}

Pero estoy experimentando un problema, los objetos que hay en la primera area, no siempre se cargan, (parece que siempre se guardan, pero al cargar, a veces se salta el 1º nodo, a veces no. O_ò

Seguiré testeando para ver si doy con la causa. Pero creo que el problema que tenía cuando abrí este tema, ya está solucionado. Creo que esta estructura está efectivamente guardando los objetos en una lista dinámica (ya tenga 1 o 16, me parece que se salvaran correctamente). Me queda meter los otros datos, la rotación, la identidad y el estado, pero creo que lo complejo ya pasó.

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...