Noticias

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

Guardar objetos y su Posicion

Iniciado por KevinLastra, Julio 18, 2017, 06:49:22 PM

Tema anterior - Siguiente tema
Buenas a todos,
 
estoy creando un juego fps 3d en el cual el personaje puede recoger y dropear objetos, cada uno de los cuales esta guardado como prefab independiente con una ID al momento que se crea, ya partiendo de ahi al momento de apagar el juego y volver, los objetos deben crearse con los mismos datos y en su posicion, bueno me puse darle vueltas como hacerlo entonses me salio esto:
 
 
 

public void Save(GameObject item,float x, float y, float z)
    {
        MaxObjToSave++;
        PlayerPrefs.SetString("SaveObjPos" + MaxObjToSave,item.GetComponent<InventoryItem>().ID);
        PlayerPrefs.SetFloat("PosX" + MaxObjToSave, x);
        PlayerPrefs.SetFloat("PosY" + MaxObjToSave, y);
        PlayerPrefs.SetFloat("PosZ" + MaxObjToSave, z);
        PlayerPrefs.SetInt("MaxObjSaved",MaxObjToSave);
    }

 
cada obj se guarda a una dirrection + el numero el cual llego( MaxObjToSave ), ahora hay que cargar esto al momento de iniciar, me salio esto
 

void Load()
    {
        for (int i = 0; i <= MaxObjToSave; i++)
        {
            ID_ = PlayerPrefs.GetString("SaveObjPos" + i,"");
            if (ID_ != "") {
                prefab = Resources.Load<GameObject>("Base + Add/" + ID_);
                GameObject item = Instantiate(prefab, transform.position, Quaternion.identity);
                item.transform.position = new Vector3(PlayerPrefs.GetFloat("PosX" + i), PlayerPrefs.GetFloat("PosY" + i), PlayerPrefs.GetFloat("PosZ" + i));
                MaxObjToSave--;
            }
        }
    }

 
el MaxObjToSave ya guardado en el save y cargado en el start del mismo script ahora lo uso para el for, entonses cargo la ID de cada obj segun su numero y se crea.
 
 
 
Ahora la razon de que estoy aqui, que este script tiene muchisimos fallos, se que voy en buen camino o eso creo, quisiera tener algun consejo o idea para tener un script funcional.
 
 
 
cualquier duda aganmelo saber porfavor.
 
aqui dejo el scrip completo...
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SaveObjDropedPos : MonoBehaviour {
 
    public List<string> itemID = new List<string>();
    public Dictionary<string, float> itemsPos = new Dictionary<string, float>();
    int MaxObjToSave;
    string ID_;
    int NumberNull;
    GameObject prefab;
    private void Awake()
    {
        MaxObjToSave = PlayerPrefs.GetInt("MaxObjSaved",0);
        Load();
    }
    public void Save(GameObject item,float x, float y, float z)
    {
        MaxObjToSave++;
        PlayerPrefs.SetString("SaveObjPos" + MaxObjToSave,item.GetComponent<InventoryItem>().ID);
        PlayerPrefs.SetFloat("PosX" + MaxObjToSave, x);
        PlayerPrefs.SetFloat("PosY" + MaxObjToSave, y);
        PlayerPrefs.SetFloat("PosZ" + MaxObjToSave, z);
        PlayerPrefs.SetInt("MaxObjSaved",MaxObjToSave);
    }
    void Load()
    {
        for (int i = 0; i <= MaxObjToSave; i++)
        {
            ID_ = PlayerPrefs.GetString("SaveObjPos" + i,"");
            if (ID_ != "") {
                prefab = Resources.Load<GameObject>("Base + Add/" + ID_);
                GameObject item = Instantiate(prefab, transform.position, Quaternion.identity);
                item.transform.position = new Vector3(PlayerPrefs.GetFloat("PosX" + i), PlayerPrefs.GetFloat("PosY" + i), PlayerPrefs.GetFloat("PosZ" + i));
                MaxObjToSave--;
            }
        }
    }
    public void Delete()
    {
        for (int i = 1; i <= MaxObjToSave; i++)
        {
            string Id = PlayerPrefs.GetString("SaveObjPos" + i);
            float x = PlayerPrefs.GetFloat("PosX" + i);
            float y = PlayerPrefs.GetFloat("PosY" + i);
            float z = PlayerPrefs.GetFloat("PosZ" + i);
            if(Id == "")
            {
                NumberNull++;
            }
            itemID.Add(Id);
            itemsPos.Add("PosX" + (i - NumberNull), x);
            itemsPos.Add("PosY" + (i - NumberNull), y);
            itemsPos.Add("PosZ" + (i - NumberNull), z);
            PlayerPrefs.DeleteKey("SaveObjPos" + i);
            PlayerPrefs.DeleteKey("PosX" + i);
            PlayerPrefs.DeleteKey("PosY" + i);
            PlayerPrefs.DeleteKey("PosZ" + i);
            MaxObjToSave = 0;
            SaveListObj();    
        }
    }
    void SaveListObj()
    {
        MaxObjToSave++;
        for (int f = 0; f <= itemsPos.Count / 3 - 1; f++) {
            for (int i = 0; i <= itemID.Count - 1; i++)
            {
                PlayerPrefs.SetString("SaveObjPos" + MaxObjToSave, itemID);
                float x = itemsPos["PosX" + f];
                float y = itemsPos["PosX" + f];
                float z = itemsPos["PosX" + f];
                PlayerPrefs.SetFloat("PosX" + MaxObjToSave, x);
                PlayerPrefs.SetFloat("PosY" + MaxObjToSave, y);
                PlayerPrefs.SetFloat("PosZ" + MaxObjToSave, z);
                PlayerPrefs.SetInt("MaxObjSaved", MaxObjToSave);
            }
        }
    }
}

 
Grasias por su atencion

Cita de: KevinLastra date=1500396562se que voy en buen camino o eso creo
   


Playerprefs != buen camino , es preferible usar siempre binario para estas cosas, acordate que playerPrefs viene el nombre de preferencias de jugador, generalmente se usa para opciones y esas cosas, pero bueno, supongamos que te funciona para lo que estas haciendo.
 
No lei el codigo pero te paso una idea, un metodo que empleo yo (totalmente inventado, seguro hay metodos mejores) es el de tener mi escena con un gran "objeto salvador", es decir un objeto vacio, que es padre de todos los items de interes. A cada obj hijo de este obj salvador le puedo poner que guarde si estan activos o no, pos, rot, scale, etc (lo que quisieras). La razon por la que los pongo hijos de este obj es porque aprovecho el id del child para comparar obj de escena nueva vs obj guardado, unity no mantiene los id iguales para distintos play's, los child de un padre si, si es que no los moves. A la hora de cargar el juego la logica hace esto:
 


  •    encontrar y recorrer los hijos del objeto salvador


  •    comparar los datos a cargar con un hijo y asignarle los datos que el archivo tenga. Si no aparece en los datos guardados (porque en la partida fue borrado) eliminar el obj de la escena.


OJO! Tene en cuenta que todo esto puede y probablemente no funcionarte para nada, porque si te diste cuenta la filosofia de esto es cargar la escena nueva y modificarla, no cargar los objetos guardados en la escena, quizas ese metodo seria mejor, es decir que si dropeas un espada y la guardas no va a haber forma de que modificando la escena nueva encuentre a la espada dropeada, no se si se entiende...Si dropeas un arma en runtime podrias decir que si esta en el mundo tirada(sin padre) se asigne automaticamente hija de este "objeto salvador" y listo, ya le diste una identidad para guardarla luego. A la hora de cargarla podes tocar un poco la logica y decir "si esta en los datos y no en la escena nueva, creala y metela en la pos", pero tene en cuenta que necesitas instanciar el prefab de la espada.. jaja es decir que tenes que ir desmarañando los pasos hasta conseguir lo que quieras, si ya tenes el prefab como decis con su id mejor.
 
Te comento este metodo porque en mi caso solo tenia que recordar si algo estaba vivo o destruido y comparar con los datos guardados, lo demas eran stats del player (facil), entonces esa jerarquia me quedaba muy bien y muy simple de hacer. Tene en cuenta que un sistema de guardado no es universal y define gran parte del juego, pensalo muy bien y adaptalo a tu caso, te interesa guardar un item dropeado por ejemplo? o guardar una rotacion? cosas asi...
 
saludos

nunca eh usado playerprefabs, ya te digo, la mayoría de cosas que eh echo en unity las eh programado de lo que sé de C#, 
 
le estas dando muchas vueltas a eso y en verdad es muy simple a mi entender...
 
yo utilizo un método pero en mis proyectos utilizo un servidor con base de datos, puedes hacer lo mismo pero en vez de guardarlo en una base de datos guardarlo en un archivo.
 
creas una clase con los atributos que quieres guardar de los objetos y el prefab al que hacen referencia, creas un diccionario para guardarlos y después lo guardas en un archivo local con JSON. 
 
fácil, rápido y eficiente   

Si no quieres usar PlayerPrefs, que escribe sobre el archivo registro de Windows, puedes utilizar un Dictionary para recopilar las variables del juego: Guardar variables del juego mediante Dictionary<string,object>

Muchas grasias me gusta mucho tu idea lightbug suena muy bien pero por fines didacticos voy ir a ver como funciona el JSON

Julio 22, 2017, 06:00:23 PM #5 Ultima modificación: Julio 22, 2017, 06:00:57 PM por KevinLastra
Bueno ya que viene al mismo tema creo que seria bien postearlo aqui mismo, @Kvashir segui tu idea y me puse a investigar lo de Json y arme este codigo que modificare en un futuro para que me sea util segun mi nesecidad, ahora mi problema esque simplemente no funciona y no se porque.
 

using System.Collections;
using UnityEngine;
using LitJson;
using System.IO;
public class SaveObjDropedPos : MonoBehaviour {
    JsonData item;
    ItemStats item_ = new ItemStats("azerty", 12, 13, 14);
    public void Start()
    {
        item = JsonUtility.ToJson(item_);
        File.WriteAllText(Application.dataPath + "/Json/ItemsPos.json",item.ToString());
    }
}

 
 

la clase que quieres convertir a json no puede heredar de MonoBehaviour, quizás ese es el problema, digo quizás, porque no as puesto el código de la clase ItemStats y tampoco as dicho que error te salta
 
XD

Etiquetas: