Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Temas recientes

Guardado de datos de enemigos

Iniciado por Mcloud, Diciembre 27, 2018, 04:42:28 PM

Tema anterior - Siguiente tema
Buenas, 
 
mi RPG en 2D avanza a buen ritmo, he llegado a un punto en el que tengo dudas, os cuento, tengo un mapa grandecillo, en el pretendo poner unos 50 enemigos(enemigo arriba enemigo abajo) el caso es que me gustaría guardar sus posiciones, vida y alguna cosa mas, entre otras cosas porque cuando mato a uno y cambio de escena, al volver aparece vivo... he pensado en un xml normal, tengo otro para datos de NPCs con los que hablo, pero me surge la duda de si englobarlos todos en 1 mismo fichero, que seria mas cómodo, o que cada 1 tenga su propio xml y así evito posibles errores de concurrencia en lectura/escritura una vez el juego esta en marcha seria menos posible, pero al cargar y que todos lean....seria de esta manera o existe alguna otra?
 
Muchas gracias
 
Un saludo

Yo lo haría separado, un archivo para los enemigos y otro para los npcs. Te aconsejo mirarte este vídeo si nunca has hecho un sistema de guardado de datos, es muy bueno.
 


   
eature=oembed" width="480">

 
 

Buenas,
 
A mi me toco pelearme tambien con esto y la mejor forma es la que te indica el compañero, y la mas segura (un fichero xml es facil de modificar desde fuera).
 
Ponles un mismo tag a todos los enemigos y a la hora de guardar metes a todos los gameObjects con ese tag en una lista con los valores que quieras guardar.
 
Luego cuando este en casa te pongo un ejemplo de como lo hice.

Cita de: leocub58 date=1545930560Yo lo haría separado, un archivo para los enemigos y otro para los npcs. Te aconsejo mirarte este vídeo si nunca has hecho un sistema de guardado de datos, es muy bueno.
   
   

      
         
eature=oembed" width="480">
      
   
   
       
   


 
 
Cita de: zelleGames date=1545988198Buenas,
   
   
      A mi me toco pelearme tambien con esto y la mejor forma es la que te indica el compañero, y la mas segura (un fichero xml es facil de modificar desde fuera).
   
   
      Ponles un mismo tag a todos los enemigos y a la hora de guardar metes a todos los gameObjects con ese tag en una lista con los valores que quieras guardar.
   
   
      Luego cuando este en casa te pongo un ejemplo de como lo hice.
   


Gracias a Los dos, he visto el video, el caso es que ya tengo montados la creación de varios XML, para el personaje, inventario, misiones y demás, todos los codifico al escribir y descodifico al leer por codigo así que por esa parte bien.
 
Ayer pude probar a crear un XML por cada enemigo, pero claro si probando tengo 12 cuando ponga más enemigos igual peto el móvil con ficheritos....me preocupa que al ponerlo en uno solo con múltiples tags, cuando cargo la escena irán todos a la vez, no dará problema de concurrencia? Según voy escribiendo pienso que no porque los va ejecutando por orden no? Y sólo podría dar problema al escribir la primera vez porque luego ya estaría creado y sólo sería leer...
 
 
 
Gracias! 

Cita de: Mcloud date=1545990093Ayer pude probar a crear un XML por cada enemigo, pero claro si probando tengo 12 cuando ponga más enemigos igual peto el móvil con ficheritos.
   

Cita de: Mcloud date=1545925348he pensado en un xml normal, tengo otro para datos de NPCs con los que hablo, pero me surge la duda de si englobarlos todos en 1 mismo fichero, que seria mas cómodo, o que cada 1 tenga su propio xml y así evito posibles errores de concurrencia en lectura/escritura una vez el juego esta en marcha seria menos posible, pero al cargar y que todos lean....seria de esta manera o existe alguna otra?
   


 
 
No, justamente la ventaja de esos archivos (ni hablar del binario) es la de organizar en arreglos muchas cosas, hacer un xml o binario de cada enemigo es una locura, siempre extendé todos tus problemas al infinito, (bueno vamos a decir a mucho), si tuvieras 3 millones de enemigos te gustaría tener 3 millones de xml's dando vuelta?? vos podés guardar las X propiedades que te interese de las Y entidades, sean enemigos, amigos, sillas, escaleras, niveles, clima, etc siempre y cuando cada entidad tenga algún identificador para que al cargar se sepa instanciar/modificar al objeto está bien. por ej para player/npc's podrías guardar Y propiedades, para props del nivel podrías guardar Z propiedades, para el sistema de clima(ponele) podrías guardar W propiedades, y así, será cuestión de armarte una clase serializable específica de cada uno, pero cuando vas a guardar usas un clase general que contenga arreglos de las anteriores.
 
 
 
 

Yo me refería hacer un xml para los enemigos y otro para los npcs, no uno por cada objeto que tengas en escena 

Cita de: leocub58 date=1546019483Yo me refería hacer un xml para los enemigos y otro para los npcs, no uno por cada objeto que tengas en escena 


jajaja si si, lo se, es porque actualmente solo tengo un NPC y crea el fichero con su nombre, utilice esa misma clase para probar el de los enemigos, pero lo tengo que cambiar lo se jeje, gracias!
 
Cita de: lightbug date=1546009452 
   
   
      No, justamente la ventaja de esos archivos (ni hablar del binario) es la de organizar en arreglos muchas cosas, hacer un xml o binario de cada enemigo es una locura, siempre extendé todos tus problemas al infinito, (bueno vamos a decir a mucho), si tuvieras 3 millones de enemigos te gustaría tener 3 millones de xml's dando vuelta?? vos podés guardar las X propiedades que te interese de las Y entidades, sean enemigos, amigos, sillas, escaleras, niveles, clima, etc siempre y cuando cada entidad tenga algún identificador para que al cargar se sepa instanciar/modificar al objeto está bien. por ej para player/npc's podrías guardar Y propiedades, para props del nivel podrías guardar Z propiedades, para el sistema de clima(ponele) podrías guardar W propiedades, y así, será cuestión de armarte una clase serializable específica de cada uno, pero cuando vas a guardar usas un clase general que contenga arreglos de las anteriores.
   
   
       
   
   
       
   


gracias!! en cuanto pueda hago los cambios en la clase y os cuento!!

Diciembre 28, 2018, 10:27:12 PM #7 Ultima modificación: Diciembre 28, 2018, 10:35:40 PM por zelleGames
Buenas,
 
te dejo un poco como lo hice yo, en mi caso tenía recursos (carbon, metal, etc...) desperdigados en el mapa y los guardaba de esta manera.
 
Aviso que la programación no es mi fuerte, jeje
 
Cree una clase estática llamada SaveLoadManager (vista en algún tutorial que no recuerdo):
 

using UnityEngine;
using System.Collections;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections.Generic;
public static class SaveLoadManager
{
//Funcion para guardar los recursos en un fichero
public static void SaveResourcesScene(ResourcesInScene resources)
    {
        BinaryFormatter bf = new BinaryFormatter();
        //GUARDA RECURSOS
        FileStream stream = new FileStream(Application.persistentDataPath + "/gameResources.sav", FileMode.Create);
        SaveResourcesData dataRes = new SaveResourcesData(resources);
        bf.Serialize(stream, dataRes);
        stream.Close();
        Debug.Log("SE GUARDA RESOURCES OK");
//Función para cargar los recursos del fichero
public static List<Recurso> LoadResources()
    {
        if (File.Exists(Application.persistentDataPath + "/gameResources.sav"))
        {
            BinaryFormatter bf = new BinaryFormatter();
            FileStream stream = new FileStream(Application.persistentDataPath + "/gameResources.sav", FileMode.Open);
            SaveResourcesData data = bf.Deserialize(stream) as SaveResourcesData;
            stream.Close();
            return data.resources;
        }
        else
        {
 
            Debug.LogError("FICHERO NO EXISTE LOAD RECURSOS");
            return null;
        }
 
    }
    }
 
  [Serializable]
public class SaveResourcesData
{
    public List<Recurso> resources;
 

    public SaveResourcesData(ResourcesInScene resourcesObjects)
    {
       // Se guardan los recursos en una lista llamando a una función que esta en otro scrip llamado ResourcesInScene
 
        resources = resourcesObjects.CheckResourcesInScene();
       
       
    }
 
}

 
 
 
Esta es la funcion que se llama para guardar en una lista los recursos de la escena
 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class ResourcesInScene : MonoBehaviour
{
//Array para recoger los gameObjects
    public GameObject[] resources;
 
//Lista para pasar los GameObejcts
    public ListaRecursos lista = new ListaRecursos();
   
//Funcion que recoge los recursos y los mete en una lista
        public List<Recurso> CheckResourcesInScene()
    {
 
   //Variable para el tipo de recurso
        int typ;
         
        resources = GameObject.FindGameObjectsWithTag("Resource");
 
        Debug.Log("HAY " + resources.Length + " EN LA ESCENA");
//Recorre el array y los va añadiendo a la lista (Hay que crear una clase serializable "Recurso" se encuentra más abajo
        for (int i = 0; i < resources.Length; i++)
        {
            //Recoge el tipo de recurso de un scriot que tiene cada recurso
            typ = resources.GetComponent<ResourceScript>().GetTipo();
 
            lista.listaRecursos.Add(new Recurso(typ, resources.transform.position.x, resources.transform.position.y, resources.transform.position.z, resources.transform.rotation.eulerAngles.x, resources.transform.rotation.eulerAngles.y, resources.transform.rotation.eulerAngles.z));
 
        }
 
     
 
        return lista.listaRecursos;
 
}
   
   
}
[Serializable]
public class Recurso
{
 
    public int tipo;
    public float xPos;
    public float yPos;
    public float zPos;
    public float xRot, yRot, zRot;
    public Recurso(int tipo, float xPos, float yPos, float zPos, float xRot, float yRot, float zRot)
    {
 
        this.tipo = tipo;
        this.xPos = xPos;
        this.yPos = yPos;
        this.zPos = zPos;
        this.xRot = xRot;
        this.yRot = yRot;
        this.zRot = zRot;
 
    }
   
 
}
 
[Serializable]
public class ListaRecursos
{
    public List<Recurso> listaRecursos;
 
}

 
 
 
 
 
Luego a la hora de cargar hago lo siguiente:
 
 
 

void LoadResources()
    {
   
       
   //Recogo en una lista los recursos guardados
        List<Recurso> resources = SaveLoadManager.LoadResources();
 
        foreach (Recurso resource in resources)
        {
            //Dependiendo del tipo de recurso instancio un prefab u otro guardados en una carpeta llamada Resources en la posición y rotación en la que encontraban
         
            switch (resource.tipo)
            {
                case 1:
                    Instantiate(Resources.Load("VETA_METAL"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                 
                    break;
 
                case 2:
                    Instantiate(Resources.Load("VETA_CRISTAL"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                 
                    break;
 
                case 3:
                    Instantiate(Resources.Load("VETA_CARBONITA"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                   
                    break;
 

                case 4:
                    Instantiate(Resources.Load("VETA_PLUTONIO"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                   
                    break;
 
            }//FIN SWITCH
        }
 

    }//FIN LOAD-RESOURCES

 
 
 
Espero te sirva de ayuda o a otra gente.
 
 
 
Saludos

Os recomiendo que guardéis los datos en JSON y uséis JsonUtility para empezar. Luego ya os complicaréis más la vida con el XML....
 
El ScriptableObject está para ayudaros...

Cita de: zelleGames date=1546032432Buenas,
   
   
      te dejo un poco como lo hice yo, en mi caso tenía recursos (carbon, metal, etc...) desperdigados en el mapa y los guardaba de esta manera.
   
   
      Aviso que la programación no es mi fuerte, jeje
   
   
      Cree una clase estática llamada SaveLoadManager (vista en algún tutorial que no recuerdo):
   
   

using UnityEngine;
using System.Collections;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections.Generic;
public static class SaveLoadManager
{
//Funcion para guardar los recursos en un fichero
public static void SaveResourcesScene(ResourcesInScene resources)
    {
        BinaryFormatter bf = new BinaryFormatter();
        //GUARDA RECURSOS
        FileStream stream = new FileStream(Application.persistentDataPath + "/gameResources.sav", FileMode.Create);
        SaveResourcesData dataRes = new SaveResourcesData(resources);
        bf.Serialize(stream, dataRes);
        stream.Close();
        Debug.Log("SE GUARDA RESOURCES OK");
//Función para cargar los recursos del fichero
public static List<Recurso> LoadResources()
    {
        if (File.Exists(Application.persistentDataPath + "/gameResources.sav"))
        {
            BinaryFormatter bf = new BinaryFormatter();
            FileStream stream = new FileStream(Application.persistentDataPath + "/gameResources.sav", FileMode.Open);
            SaveResourcesData data = bf.Deserialize(stream) as SaveResourcesData;
            stream.Close();
            return data.resources;
        }
        else
        {
 
            Debug.LogError("FICHERO NO EXISTE LOAD RECURSOS");
            return null;
        }
 
    }
    }
 
  [Serializable]
public class SaveResourcesData
{
    public List<Recurso> resources;
 

    public SaveResourcesData(ResourcesInScene resourcesObjects)
    {
       // Se guardan los recursos en una lista llamando a una función que esta en otro scrip llamado ResourcesInScene
 
        resources = resourcesObjects.CheckResourcesInScene();
       
       
    }
 
}

   
       
   
   
      Esta es la funcion que se llama para guardar en una lista los recursos de la escena
   
   

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class ResourcesInScene : MonoBehaviour
{
//Array para recoger los gameObjects
    public GameObject[] resources;
 
//Lista para pasar los GameObejcts
    public ListaRecursos lista = new ListaRecursos();
   
//Funcion que recoge los recursos y los mete en una lista
        public List<Recurso> CheckResourcesInScene()
    {
 
   //Variable para el tipo de recurso
        int typ;
         
        resources = GameObject.FindGameObjectsWithTag("Resource");
 
        Debug.Log("HAY " + resources.Length + " EN LA ESCENA");
//Recorre el array y los va añadiendo a la lista (Hay que crear una clase serializable "Recurso" se encuentra más abajo
        for (int i = 0; i < resources.Length; i++)
        {
            //Recoge el tipo de recurso de un scriot que tiene cada recurso
            typ = resources.GetComponent<ResourceScript>().GetTipo();
 
            lista.listaRecursos.Add(new Recurso(typ, resources.transform.position.x, resources.transform.position.y, resources.transform.position.z, resources.transform.rotation.eulerAngles.x, resources.transform.rotation.eulerAngles.y, resources.transform.rotation.eulerAngles.z));
 
        }
 
     
 
        return lista.listaRecursos;
 
}
   
   
}
[Serializable]
public class Recurso
{
 
    public int tipo;
    public float xPos;
    public float yPos;
    public float zPos;
    public float xRot, yRot, zRot;
    public Recurso(int tipo, float xPos, float yPos, float zPos, float xRot, float yRot, float zRot)
    {
 
        this.tipo = tipo;
        this.xPos = xPos;
        this.yPos = yPos;
        this.zPos = zPos;
        this.xRot = xRot;
        this.yRot = yRot;
        this.zRot = zRot;
 
    }
   
 
}
 
[Serializable]
public class ListaRecursos
{
    public List<Recurso> listaRecursos;
 
}

   
       
   
   
       
   
   
      Luego a la hora de cargar hago lo siguiente:
   
   
       
   
   

void LoadResources()
    {
   
       
   //Recogo en una lista los recursos guardados
        List<Recurso> resources = SaveLoadManager.LoadResources();
 
        foreach (Recurso resource in resources)
        {
            //Dependiendo del tipo de recurso instancio un prefab u otro guardados en una carpeta llamada Resources en la posición y rotación en la que encontraban
         
            switch (resource.tipo)
            {
                case 1:
                    Instantiate(Resources.Load("VETA_METAL"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                 
                    break;
 
                case 2:
                    Instantiate(Resources.Load("VETA_CRISTAL"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                 
                    break;
 
                case 3:
                    Instantiate(Resources.Load("VETA_CARBONITA"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                   
                    break;
 

                case 4:
                    Instantiate(Resources.Load("VETA_PLUTONIO"), new Vector3(resource.xPos, resource.yPos, resource.zPos), Quaternion.Euler(resource.xRot, resource.yRot, resource.zRot));
                   
                    break;
 
            }//FIN SWITCH
        }
 

    }//FIN LOAD-RESOURCES

   
       
   
   
      Espero te sirva de ayuda o a otra gente.
   
   
       
   
   
      Saludos
   


Muchisimas gracias, lo tengo muy parecido, lo unico que encontre unos ejemplos para codificar y descodificar y es lo que uso en vez de serializar, funciona perfecto asi que prefiero no tocarlo jeje, pero me has dado ideas, gracias!!
 
 
 
 
 
Cita de: pioj date=1546088032Os recomiendo que guardéis los datos en JSON y uséis JsonUtility para empezar. Luego ya os complicaréis más la vida con el XML....
   
   
      El ScriptableObject está para ayudaros...
   


Gracias Pioj, el caso es que lo tengo ya todo montado con xml y a priori me es mas facil, no he visto nada de json y mira que he oido hablar de ellos por aqui....

Etiquetas: