Jump to content
enelmenu

Reset some things - Resetear algunas cosas hehe

Recommended Posts

Hola. <3

Necesito resetear cada nivel, nose como hacerlo, conosco que existe la libreria "UnityEngine.SceneManagement", se como reiniciar una Scena mas omenos facilongo, pero necesito algo mas complejo...
 

Cada ves que me caigo me reinicio PERO tengo que reiniciar mis plataformas, placas, Player,puntos, y algunas que otras cositas, MENOS la camara y la variable de rotacion de los puntos. 

Basicamente resetear determinadas cosas(GameObjects) de una scena.

Para que??

  • Necesito mantener la fluides de mi camara, por ende no necesita ser reiniciada su pocision.
  • -                    idem               - de mi rotacion del score, reiniciando la posicion de los score(puntos), pero no la rotacion.

Respuestas? 

  • Si puede haber.

Saludos?

  • Si hay.

Abrazo?

  • Tambien
  • Espero respuestas
  • Att:
    • enelmenu
      • Firma Oficial
        • (R)

Share this post


Link to post
Share on other sites

@TheBullet Sep, por ahi va la mano, estube probando, pero me crea infinitos cuando reseteo el lvl, como arreglo eso?

using UnityEngine;
// script camera DontDestroyInReset
public class DontDestroyLoadCamera : MonoBehaviour {

	private void Awake() {
		DontDestroyOnLoad(transform.gameObject);
	}
}

Crea un GameObject en DontDestroyOnLoad por reset, lo cual es un problema, como hago para que no se recreen?

Share this post


Link to post
Share on other sites
hace 1 hora, enelmenu said:

@TheBullet Sep, por ahi va la mano, estube probando, pero me crea infinitos cuando reseteo el lvl, como arreglo eso?


using UnityEngine;
// script camera DontDestroyInReset
public class DontDestroyLoadCamera : MonoBehaviour {

	private void Awake() {
		DontDestroyOnLoad(transform.gameObject);
	}
}

Crea un GameObject en DontDestroyOnLoad por reset, lo cual es un problema, como hago para que no se recreen?

using UnityEngine;

public class DontDestroyLoadCamera : MonoBehaviour {  
	public static DontDestroyLoadCamera instance;
	private void Awake() 
	{
		if (instance == null)
		{
			DontDestroyOnLoad(transform.gameObject);
			intance = this;
		}
		else
			Destroy(this.gameObject);   
	}
}

Se guarda el script, si el script ya se ha asignado antes quiere decir que ya existe y se elimina el objeto.

Edited by TheBullet

Share this post


Link to post
Share on other sites

Solucionado, dejo mis algoritmos(? jajaja quedo bastante picante se los comparto

using UnityEngine;
using UnityEngine.SceneManagement;
// GameObject Level o algun GameObject estilo managger que tengan

public class Level : MonoBehaviour {
	[Header("Notes")]
	public string ResetLevelHere = "Don't remove script.";

	private static string sceneName;

	private void Awake() {
		sceneName = SceneManager.GetActiveScene().name;
		DontDestroyLoadCamera.InstanceCamera();
	}

	public static void ResetLevel () {
		SceneManager.LoadScene(sceneName);
	}
}
using UnityEngine;
using UnityEngine.SceneManagement;

public class DontDestroyLoadCamera : MonoBehaviour {
	
	// instantiate empieza null, se llama una sola vez itera una sola vez en Awake de Level.
	private static GameObject instanceCamera = null;
	// target(gameobject) que quieran (prefab) tambien tendrian q cambiar el nombre del script
  	private static GameObject Camera;
  	// aca un mini algoritmo para que puedan buscar su targetInterno en mi caso necesito encontrar mi player
  	// como tenemos nuestro gameobject(prefab dontDestroy) en otra scena(DontDestroyOnLoad)
  	// esto simplemente busca determinado GmObjt en todas las escenas
	public static GameObject[] GoAllFindScenes;

	public static GameObject InstanceCamera() {
		// una sola iteracion en if
      	if (instanceCamera == null) {
			Camera = Instantiate(Resources.Load("Camera", typeof(GameObject))) as GameObject;
			instanceCamera = Camera;
			DontDestroyOnLoad(instanceCamera);
		}
       // itera cada Reset 
		GoAllFindScenes =  GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];
		foreach (GameObject go in GoAllFindScenes)
		{
			MoveCamera.player = GameObject.Find("Player");
		}
		return instanceCamera;
	}
}
using UnityEngine;

public class DropReset : MonoBehaviour {

	void Update()
	{	
		// Hi! i Drop(me cai necesito reiniciarme) u.u
      	if (transform.position.y < 5)
          Level.ResetLevel();
	}
}

 

Gracias @TheBullet 
Saludos!!!

Edited by enelmenu

Share this post


Link to post
Share on other sites
18 hours ago, enelmenu said:

Para que??

  • Necesito mantener la fluides de mi camara, por ende no necesita ser reiniciada su pocision.
  • -                    idem               - de mi rotacion del score, reiniciando la posicion de los score(puntos), pero no la rotacion.

Respuestas? 

  • Si puede haber.

Sabes que si no hay respuestas se las inventa no? jajaj.

Hay cosas que no me cierran por ej:

GoAllFindScenes =  GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];
  foreach (GameObject go in GoAllFindScenes)
  {
  	MoveCamera.player = GameObject.Find("Player");
  }
  
return instanceCamera;

y "go" ? porque haces ese foreach buscando al Player para todos los gameObjects?

 

Podes crear un script (o gregarle a uno conocido) que tenga la posibilidad de tomar una señal de Reset (o un evento quizas) y  actuar acorde. Dentro del script podrias poner el que resetear, pos, rot, valores de un componente(podria ser un script tuyo, investiga esto https://docs.unity3d.com/ScriptReference/MonoBehaviour.Reset.html), etc. El scrip debe encargarse de entrada de guardar los datos que va a recuperar luego Pos, Rot, escala, componentes, etc.

Por ejemplo si tu Player muriera (RIP) (En el codigo ejemplo Player.instance.isDead())

Event_Manager.cs

using System.Collections.Generic;
using UnityEngine;

public class Event_Manager : MonoBehaviour {	

	public delegate void PlayerDeadDelegate ();
	public static event PlayerDeadDelegate PlayerDead;


	void Update () {
		
		if (Player.instance.isDead ())
			if (PlayerDead != null)
				PlayerDead ();
	}
}

Y en tus scripts a resetear:

void OnEnable () {
		...
		//Reset empieza a escuchar al evento PlayerDead
		//Cuando ocurre el evento se llama a Reset()
		Event_Manager.PlayerDead += Reset;	
		

	}

	void OnDisable()
	{
		//Reset deja de escuchar al evento PlayerDead
		Event_Manager.PlayerDead -= Reset;
	}

	void Reset()
	{
		
		//si EL SCRIPT fuera de una plataforma resear pos, rot, valores de componentes		

		//si EL SCRIPT fuera de un score resear pos

		//OJO no van if's creas distintos "Reset()" en cada script
	}

Entonces, el player muere, el player aparecera donde deba, los gameObjects que esten escuchando al evento PlayerDead dispararan su Reset() y cada uno recuperara lo que tenga, no tenes ningun DontDestroyOnLoad ni nunguna carga de escena.

Si te anda como esta joya, solo para agregar lo de los eventos que en este tipo de cosas en el que algo dispara cosas diferentes es muy uitl, tambien podrias por codigo llamar a distintos reset de distintos gameObjects tambien, tendrias que buscarlos previamente, esto es algo mas comodo si es que superas lo de las delegate.

Saludos

Edited by lightbug

Share this post


Link to post
Share on other sites
hace 6 horas, lightbug said:

y "go" ? porque haces ese foreach buscando al Player para todos los gameObjects?

		foreach (GameObject go in GoAllFindScenes) {
			if (go.gameObject.name == "Player")
				MoveCamera.player = go.gameObject;
		}

Seria asi, nose por que lo escribi mal, encima funiconaba hmmmm pero claro iteraba como loco, ahi va tranqui



No entiendo tu concepto, osea vos decis, envez de crear otra scena, con la libreria mannager scene y dar muchas vueltas... directamente, resetear, transform, components en la misma scena determinado GameObject....:35_thinking::35_thinking:

Sinceramente no entendi ni el tipo de dato delegate, ni los eventos.

Pero la cuestion la entiendo, creo.
Bueno me parece perfecto hacerlo mas comodo y sin separar scenas, lo cual me jode bastante, tengo varios Awake que llaman el GameObject.Find() y me caga cuando separo en otra scena.

Asi que lo voy a hacer como vos decis.
Ahora bien... yo por ejemplo, tengo esto en mi scena....
 

Level Nº

  • Lighting
  • Particle Crush
  • Player
  • Level
    • Loops
    • Statics
    • Moves
    • Obstacles
    • Points
    • ColBarriers
  • FinishLevel

DontDestroyOnLoad

  • Camera

Okey, la camara vamos a dejarla de lado, simplemente la dejo ahi para no tener ningun enconveniente

Yo en Level tengo mi script manager digamosle asi, el que contiene mi data para los resets.
Y Player es el que acciona esa data, yo en player tengo mi script con una condicion donde si mi transform.position.y < -5 Active la funcion Level.Reset() y se auto resetea, tiene su propio reset, ok?

Bueno nos situamos en Reset() dentro de mi script Level...

Ahora mismo, yo soy la funcion(Reset()), y exijo que si me llaman, voy a resetear los componentes y transforms de:

  • Statics
  • Moves
  • Obstacles
  • Points
  • ColBarriers

MENOS "Loops" (Por que? En loops tengo mis platforms loops donde no necesitan ser reseteadas, una vez q accionan necesito que su fluides continue, por ende, no se resetea ni el transform ni sus componentes ), de lo contrario mis platforms moves por ejemplo, si necesitan ser reseteadas, junto con sus plates, y demas....

Teniendo en cuenta que cada GameObject a los que me refieron son Padres:

  • Statics
    • cube
    • cube2
    • cube3
  • Moves
    • Plates
      • plate
      • plate
      • plate
    • M1
      • PlatformMove
    • M2
      • PlatformMove
    • M3
      • PlatformMove
  • Blablabla

Resetear el padre completo, con todos sus hijos, resetear completamente.

Okey... como hago esto?? no debe ser algo tan complicado, si vas a usar los delegates, y eventos explicame un poquito.

Teamo abrazo :134_spy::95_v:

Edited by enelmenu

Share this post


Link to post
Share on other sites
21 hours ago, enelmenu said:

Seria asi, nose por que lo escribi mal, encima funiconaba hmmmm pero claro iteraba como loco, ahi va tranqui

Seguis iterando igual, lo unico que ahora no buscas el Player sino lo comparas, porque de entrada no guardas el player por nombre (para seguir como lo tenias aunque no me van los nombres) y listo, no iteras, con un GameObject.Find busca hasta encontrar el nombre que le pasas, no es necesario iterar.

 

21 hours ago, enelmenu said:

No entiendo tu concepto, osea vos decis, envez de crear otra scena, con la libreria mannager scene y dar muchas vueltas... directamente, resetear, transform, components en la misma scena determinado GameObject....:35_thinking::35_thinking:

Sinceramente no entendi ni el tipo de dato delegate, ni los eventos.

Pero la cuestion la entiendo, creo.
Bueno me parece perfecto hacerlo mas comodo y sin separar scenas, lo cual me jode bastante, tengo varios Awake que llaman el GameObject.Find() y me caga cuando separo en otra scena.

Asi que lo voy a hacer como vos decis.
Ahora bien... yo por ejemplo, tengo esto en mi scena....

Crear o cargar una escena implica sacar de la "lista" de gameObjects a todos y cargar y resetear la escena destino, de aca esas minipausas cuando cargas algo, si no queres las recargar devuelta haces todo dentro de la misma escena (sin scenemanager), por eso plantee lo del Reset y el evento(solo para llamar a los reset). Fijate que no es lo mismo que cambiar la posicion o la rotacion, pensalo como cuando haces Object pooling con proyectiles, vos no instancias/destruis a cada segundo porque es costoso y da lugar a picos de performance si tenes muchos proyectiels, lo que haces es simplemente mover el proyectil dando la ilusion de que reseteo la posicion original, aca podes hacer esta analogia (algo asi, sin los problemas de performance cuadro a cuadro).

Vos te estas enfocando en tal y tal objeto, cuando deberias enfocarte en tal y tal script, si sos una plataforma, hace el reset de determinada forma, si sos un score girando hacelo de tal forma, si sos otra cosas hacelo de otra forma y asi... si, tenes que escribir un reset para todos los distintos "Tipos de reset", Aunque podes generalizarlo y agregar un solo script Reset que te de booleanas publicas en el que le seteas que vas a resetear:

public class ResetScript : Monobehaviour
{
	Vector3 Pos;
	Quaternion Rot;
	Vector3 Scale;

	//para meter algunos componentes tuyos
	public ComponenteTuyo1 comp1;
	public ComponenteTuyo2 comp2;

	public bool resetPos = true;
	public bool resetRot = true;
	public bool resetScale = true;
	

	void OnEnable()
	{
		//te anotas al evento (lo del script anterior)
		
		//guardas los datos a guardar, aca son muy poquitos podes guardar todo si quisieras (sin los if's)

		if(resetPos)
			Pos = transform.position;
		
		if(resetRot)
			Rot = transform.rotation;

		//... y asi
	}

	void OnDisable()
	{
		//te desanotas al evento (lo del script anterior)
	}
	
	void Reset()
	{
		if(resetPos)
			transform.position = Pos;
		
		if(resetRot)
			transform.rotation = Rot;
		
		//para los componentes fijate el monobehaviour.Reset (q te pase arriba)
		//... y asi
	}
	
}

Cuando pasa el evento se resetea todo, si lo haces asi tenes que agregar este script en todo lo reseteable, el otro metodo es escribir un reset para cada tipo, si tenes dos o tres o cuatro tipos de resets (pos, roto, scale, etc) te recomiendo escribir un reset para cada uno, te ahorras de meter un componente mas (el Reset anterior) a todos los reseteables, por otro lado si tenes muchos tipos reseteables lo mejor seria generalizarlo mas como en el ejemplo delscript este. Incluso podrias crear prefabs para alivianar el trabajo mas aun.

 

21 hours ago, enelmenu said:

Okey... como hago esto?? no debe ser algo tan complicado, si vas a usar los delegates, y eventos explicame un poquito.

Mira de eventos no lo manejo muy bien, es relativamente simple setearlo, pero podes usar lo que quieras para llamar al reset, podrias poner un script en el padre de todo, que cuando muera el player, recorra a sus hijos/nietos/bisnietos/... y dependiendo del tipo de objeto que sea le de su reset, totalmente valido y sin problemas, pero te la queria complicar un poco mas jajaja.

las delegates son:

Un delegado en C# es similar a un puntero a una función en C o C++. El uso de un delegado permite al programador encapsular una referencia a un método dentro de un objeto delegado. El objeto delegado se puede pasar entonces al código, el cual puede llamar al método de referencia, sin tener que conocer en tiempo de compilación qué método se debe invocar.

Entonces su uso en los eventos es algo logico ¿?, si ya se es confuso o por lo menos no me crie con esto y cuesta entenderlo bien (sobre todo si dedicaste 2 min a estudiarlo como yo), pero te diria que no es algo para estudiar a fondo fondo para lo que queres, si despues tenes tiempo y queres claro podes hacerlo, pero si te limitas a escribir eventos (si es que lo usas) de esta forma yo diria que no necesitas mas delegates, la cuestion es el evento necesita el delegate, listo fueee. Por cierto los eventos los aprendi de la pagina oficial de aprendizaje de Unity, antes ni sabia que existian.

Edited by lightbug

Share this post


Link to post
Share on other sites

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