Jump to content
UnitySpain
Sign in to follow this  
arganthammer

Guardado y carga de posición y otros

Recommended Posts

Hola de nuevo. Elaboré este código para guardar la posición y rotación de los bloques etiquetados como "Bloque" con la G, y poder cargarla con la C. Parece que funciona bien. Perdonad, pero no sé como funciona esto de poner el código con pastebin:

private List<GameObject> obj;
private List<Vector3> pos;
private List<Quaternion> rot;
private void FixedUpdate() {
    if (Input.GetKeyDown(KeyCode.G)) {
        int i = 0;
        GameObject[] bloque;
        bloque = GameObject.FindGameObjectsWithTag("Bloque");
        obj = new List<GameObject>();
        pos = new List<Vector3>();
        rot = new List<Quaternion>();
        foreach (GameObject r in bloque) {
            obj.Add(r);
            pos.Add(obj[i].transform.position);
            rot.Add(obj[i].transform.rotation);
            i++;
        }
    }
    if (Input.GetKeyDown(KeyCode.C)) {
        for (int i = 0; i < obj.Count; i++) {
            obj[i].transform.position = pos[i];
            obj[i].transform.rotation = rot[i];
        }
    }
}

El problema es que durante el juego un bloque puede volverse una pared, y en este caso se le cambia la etiqueta y se le desactiva su script (es necesario). Otras veces incluso desactivo estos bloques para "destruirlos", dependiendo. Para que cargase y todo volviera a ser como antes, tenía que volver a corregir las etiquetas, activar de nuevo el script, y activar otros bloques. Pensé que funcionaría poner lo siguiente dentro del for de la carga:

if (obj[i].tag != "Bloque") {
    obj[i].tag = "Bloque"; //Le devuelve su tag, parece que no hay problema con esto
    if (obj[i].GetComponent<Stone_Block>().enabled == false) { //*Lo explico ahora*
        obj[i].GetComponent<Stone_Block>().enabled = true;
    }
}
if (!obj[i].activeSelf) { //Para activar los bloques que se desactivan. Da el error de que la coroutine no puede empezar por estar el objeto inactivo, ¿debería sacar su desactivación de la coroutine del objeto?
    obj[i].SetActive(true);
}

*El caso es que cada tipo de bloque tiene un script. El de piedra el Stone_Block, el de hielo, el Ice_Block... etc. Tendría que poner donde compruebo y activo el script un else if con cada uno de los tipos de bloque, pero al parecer cuando hace la comprobación de si un script está desactivado, y ese script no lo tiene un objeto, no funciona bien. ¿No hay alguna forma de activar los script desactivados de cada objeto de una forma general? La verdad es qué no entiendo qué es lo que pasa, y hacer las cosas de otro modo muy distinto no lo entendería muy bien. Perdonad si no puedo responder en poco tiempo y gracias por adelantado.

Edited by pioj
Por favor, usa el <> o el "quote" para pegar código.

Share this post


Link to post
Share on other sites

Saludos Arganthamer

Igual que has creado listas para guardar la posición y rotación, creo que puedes crear también listas para guardar y cargar esos datos particulares. (Una lista que guarde el tipo de bloque qué es y acudes a ella a la hora de cargarlo, si es un bloque de fuego, le guardo el valor 1, si es de aire le guardo el valor 2, y al cargar pues mires, es un valor 1, es un bloque de fuego, cargas el prefab y la textura correspondiente).

 

Sobre como comprobar el tipo de bloque qué es, entiendo que la diferencia es un tipo de script particular, sí, la idea de poner los if - else if para comprobar cada tipo de script podría ser una forma que funcione, aunque a mi no me gusta mucho.... >_<  También está el switch case, pero es que yo creo que esta situación se podría solventar mejor mediante la práctica del polimorfismo.

 

El plan que propongo sería crear un script base para los bloques, que sea como el padre (¿"bloque.cs"?), y luego, los scripts hijos que tengan las particularidades de cada bloque. ("bloque_fuego.cs", "bloque_hielo.cs" etc...). 

El script padre, tendría todas esas variables y funciones que son recurrentes en todos los hijos, (también podría hacer uso de las funciones virtuales, pero bueno, mejor que no me vaya por los cerros de Úbeda ahora mismo). No sé, supón que todos los bloques tienen una vida, que llegada  0 el bloque se destruye, da igual si es fuego, hielo o lo que sea, todos tienen vida, pues ese dato iría al código padre. También creo que iría muy bien una lista Enum que sea la que diga que tipo de bloque será (los códigos hijos serán los encargados de inicializarla).

Luego, los códigos hijos, heredarían el código padre, (por lo que todos tienen el valor vida, y todos tienen acceso a la variable tipo, luego al empezar el código fuego, entre sus primeras acciones es decirle a la padre, "ey, que yo soy de fuego") pero cada script, pues tiene además sus particularidades (los bloques de hielo tienen variables y funciones de deslizamiento... los bloques de fuego tienen variables del daño que provocan... etc...)

Cuando creas un bloque, no pones el script padre, pones el script hijo que sea, pero por herencia, todos tienen ese script padre (e inicializan la variable tipo del padre), luego a la hora de guardar y cargar, no preguntas si tiene la clases hijos que pueden ser muchas, si no que preguntas directamente por la clase padre.

En vez de preguntar

  • ¿tiene el script "Bloque_Fuego"? ,
    • si , es de tipo bloque fuego
    • no, ¿tiene el script "Bloque_Hielo"?,
      • si, es del tipo bloque hielo
      • no, ¿tiene el script "Bloque_Tierra"?
        • si, es del tipo bloque tierra
        • no, no es un bloque....

Pues preguntas

  • ¿tiene el script Bloque?  
  • Sí - pues mira su variable tipo.
  • No- pues no es un bloque.

 

(Puedes crear dicha conexión padre-hijo llamando el script padre en la declaración del hijo.

public class Bloque_Base : MonoBehaviour
{
	enum TipoDeBloque {SinDefinir ,Hielo, Fuego, Tierra};
	TipoDeBloque _tipo;	//Esta variable se puede leer desde los tres scripts
}

public class Bloque_Hielo : Bloque_Base   //Esta clase hereda la clase Bloque_Base, que a su vez, hereda también la clase MonoBehaviour de Unity
{
	float Deslizamiento;	//Esta variable sólo se puede leer desde este script
}

public class Bloque_Fuego : Bloque_Base	//Esta clase hereda la clase Bloque_Base, que a su vez, hereda también la clase MonoBehaviour de Unity
{
	float Dolor;	//Esta variable sólo se puede leer desde este script
}

 

 

Share this post


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

×