Noticias

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

Activar/Desactivar un Gameobject

Iniciado por ramunda, Julio 08, 2016, 01:21:23 AM

Tema anterior - Siguiente tema
Julio 08, 2016, 01:21:23 AM Ultima modificación: Julio 08, 2016, 05:10:30 PM por pioj
Buenas noches,
 
Tengo una duda y después de mucho buscar recurro a ustedes,
 
Explico:
 
Tengo una escena(la principal), con un menú de niveles, bien , selecciono nivel 1 y la desactivo al cargar la siguiente escena.
 
dicho GameObject lleva un script de DontDestroyOnLoad (this.gameObject); añadido a el para que lo cargue en cada escena y pueda encontrarlo en las posteriores.
 
la desactivo de esta manera:
 

void Update ()
{
   if(nivel1)
   {
      Application.LoadLevel("leñador");
      selectniveles.SetActive(false);
   }

 
Hasta aquí de perlas, el juego empieza y bien.
 
El problema es cuando termino el nivel1 intento activar de nuevo el mencionado GameObject, pero no hay manera.
 
Tengo entendido que Unity no encuentra GO (GameObject) desactivados....
 
He probado:
 



   
      GameObject.Find("selectniveles").SetActive(true);
   

[/quote]
 
y todas las maneras activables, pero nada.
 
No encuentra el GO.....
 
Alguna idea de como activarlo?
 
 
 
Gracias de antemano.

Julio 08, 2016, 09:29:13 AM #1 Ultima modificación: Julio 09, 2016, 06:11:03 PM por kaito
Esta pregunta ya ha salido varias veces en el foro.
 
 
 
Las funciones de la clase GameObject que realizan búsquedas, es decir: GameObject.Find, GameObject.FindWithTag, etc... no funcionan con GameObjects desactivados.
 
Soluciones:
 
1) La función de búsqueda del componente Transform, como Transform.FindChild Transform.Find, sí que funcionan con GameObjects desactivados. Emparenta dentro de un GameObject vacío los GameObjects que necesites desactivar/activar durante el juego.
 
2) Crear un marcador al GameObject desactivado dentro del script tipo singleton/único con una variable estática:
 

using UnityEngine;
using System.Collections;
public class Menu : MonoBehaviour {
    public static GameObject singleton;
       
void Awake () {
        if (singleton) Destroy(this.gameObject);
        else singleton = this.gameObject;
}

 
Entonces, podrás acceder en todo momento al menú mediante Menu.singleton, esté activado o desactivado.

Julio 08, 2016, 10:09:40 AM #2 Ultima modificación: Julio 08, 2016, 02:04:51 PM por ramunda
Cita de: kaito date=1467962953Esta pregunta ya ha salido varias veces en el foro.
   
   
       
   
   
      Las funciones de la clase GameObject que realizan búsquedas, es decir: GameObject.Find, GameObject.FindWithTag, etc... no funcionan con GameObjects desactivados.
   
   
      Soluciones:
   
   
      1) La función de búsqueda del componente Transform, como Transform.FindChild, sí que funcionan con GameObjects desactivados. Emparenta dentro de un GameObject vacío los GameObjects que necesites desactivar/activar durante el juego.
   
   
      2) Crear un marcador al GameObject desactivado dentro del script tipo singleton/único con una variable estática:
   
   

using UnityEngine;
using System.Collections;
public class Menu : MonoBehaviour {
    public static GameObject singleton;
       
void Awake () {
        if (singleton) Destroy(this.gameObject);
        else singleton = this.gameObject;
}

   
      Entonces, podrás acceder en todo momento al menú mediante Menu.singleton, esté activado o desactivado.
   


Muchas gracias Kaito por la respuesta, tenía esta posibilidad en mente pero el GameObject es un UI, y si lo pongo dentro de otro Go no se carga en pantalla, bastaría con agregarle un script como he echo con Dontestroy on load?., deberia funcionar?
 
Gracias
 
 
 
 

Julio 08, 2016, 06:36:12 PM #3 Ultima modificación: Julio 08, 2016, 06:38:41 PM por kaito
Si el GameObject es un UI, entonces ya se encuentra emparentado como mínimo al GameObject del componente Canvas que siempre se encuentra activo, y no necesitas crear un GameObject vacío.
 
Entonces buscas el GameObject del Canvas y buscas el UI desde su componente Transform, sería: GameObject.Find("Canvas").transform.FindChild("UI").gameObject;

Cita de: kaito date=1467995772Si el GameObject es un UI, entonces ya se encuentra emparentado como mínimo al GameObject del componente Canvas que siempre se encuentra activo, y no necesitas crear un GameObject vacío.
   
   
      Entonces buscas el GameObject del Canvas y buscas el UI desde su componente Transform, sería: GameObject.Find("Canvas").transform.FindChild("UI").gameObject;
   


Kaito, gracias, gracias por tu tiempo , pro me sigue sin funcionar, y es culpa mía , no me he expresado con claridad seguramente y por eso no me funciona.
 
Voy paso por paso con toda la info:
 
El objeto al que quiero acceder y a sus hijos es:
 
selectniveles, adjunto foto.
 
lleva dos scripts :
 
Dontdestoy on load :
 

using UnityEngine;
using System.Collections;
public class dontdestroy : MonoBehaviour {
// Use this for initialization
void Awake ()
{
   DontDestroyOnLoad (this.gameObject);

}

}

 
y otro que lo serializa tal y como tu me has dicho;
 

using UnityEngine;
using System.Collections;
public class Intro : MonoBehaviour {
public static GameObject singleton;
   void Awake () {
      if (singleton) Destroy(this.gameObject);
      else singleton = this.gameObject;
   }
}

 
Bien , cuando carga esta escena, que lo que hace es darte a elegir un nivel, se va a la escena1 , pero se va desactivada:
 

public GameObject selectniveles;
void Update ()
{
   if (nivel1) {
      Application.LoadLevel ("leñador");
      selectniveles.SetActive (false);
   }

 
bien, hasta aquí,  el level leñador empieza limpio y todo bien.
 
Lo que quiero es, desde la escena leñador , acceder a selectniveles y a sus hijos....pero no hay manera!!
 
he probado lo que me has dicho con el transform...pero nada me sigue diciendo que le objeto no se encuentra.
 
tambien he probado con Info.singleton.selectniveles.SetActive(true) y se activa si, pero desaparece a los 2 segundos.
 
y he probado:
 
Info.singleton.FindChild("nivel2").SetActive(true); y nada de nada.
 
 
 
Algo estoy haciendo mal.....:(
 
 
 
 
 
 
 
 
 






   
      Info.singleton.FindChild("nivel2").SetActive(true); y nada de nada.
   

[/quote]
 
No funciona porque el GameObject padre está desactivado. Para buscar desde el componente Transform necesitas que el GameObject padre este siempre activo, si no es así necesitas crear un GameObject vacio.
 
 
 



   
      Info.singleton.selectniveles.SetActive(true) y se activa si, pero desaparece a los 2 segundos
   

[/quote]
 
??? Eso en principio, debería ser Info.singleton.SetActive(true), ya que el script Intro debe ir en el GameObject 'selectniveles'. Yo lo he testeado en otro script y funciona la activación/desactivación desde otros GameObject.
 
El script donde se encuentra la variable GameObject selectniveles esta incompleto y posiblemente el fallo se encuentre en ese script.

Cita de: kaito date=1468015788No funciona porque el GameObject padre está desactivado. Para buscar desde el componente Transform necesitas que el GameObject padre este siempre activo, si no es así necesitas crear un GameObject vacio.
   
   
       
   
   
      ??? Eso en principio, debería ser Info.singleton.SetActive(true), ya que el script Intro debe ir en el GameObject 'selectniveles'. Yo lo he testeado en otro script y funciona la activación/desactivación desde otros GameObject.
   
   
      El script donde se encuentra la variable GameObject selectniveles esta incompleto y posiblemente el fallo se encuentre en ese script.
   


Vale , ya voy entendiendo mas y mas.
 
Ademas se me fue la pinza....Donde llamamos a Info...es Intro...pero da igual no funciona igual.
 
El GameObject padre en este caso como bien ya sabes, es un Ui, si l metes en un GO vacio deja de aparecer en pantalla.....ya lo he probado.
 
Pero si bien dices que el Go padre tiene que estar activo....
 
Si lo activo;
 

Intro.singleton.SetActive(true);

 
y después llamo a los Child.....debería funcionar no?:
 

Intro.singleton.FindChild("nivel2").SetActive(true);

 
pues...no :(
 
Cita de: kaito date=1468015788El script donde se encuentra la variable GameObject selectniveles esta incompleto y posiblemente el fallo se encuentre en ese script.
   


Supongo que te refieres al update donde desactivo el selectniveles, eso es solo un fragmento para que vieras como lo declaraba.
 
el script completo es este:
 

using UnityEngine;
public class selectlevels : MonoBehaviour
{
private bool nivel1 = false;
private bool nivel2 = false;
private bool nivel3 = false;
private bool nivel4 = false;
private bool salir = false;
private bool menu = false;
public GameObject selectniveles;
 
void Update ()
{
   if (nivel1) {
      Application.LoadLevel ("leñador");
      selectniveles.SetActive (false);
   }
   if (nivel2) {
      Application.LoadLevel ("leñadornivel2");
   }
   if (nivel3) {
      Application.LoadLevel ("leñadornivel3");
   }
   if (salir) {
      Application.Quit ();
   }
   if (nivel4) {
      Application.LoadLevel ("leñadornivel4");
   }
   if (menu) {
      Application.LoadLevel ("menu");
   }
}
public void Nivel1()
{
   nivel1 = true;
}
public void Nivel2()
{
   nivel2 = true;
}
public void Nivel3()
{
   nivel3 = true;
}
public void Nivel4()
{
   nivel4 = true;
}
public void salida()
{
   salir = true;
}
public void Menu()
{
   menu = true;
}
}

 
es el sistema que uso para los botones ya que se trata de un juego para móviles.
 
alguna idea de como mantener siempre vivo ese Go, y que se vea en pantalla?, o otra manera de desactivarlo al pasar al nivel de juego.
 
Aux aprecio la ayuda Kaito. ;)
 
 
 
 
 
 
 
 

Creo que el fallo se encuentra en el script selectlevels, ya que no reinicias las variables bool a false cuando cambias de nivel. Entonces, puede producir un error al quedar una o más variables en true.
 
 
 
Modifica esta parte de código, añadiendo un reinicio a false de la variable bool:
 
 
 

   void Update ()
{
   if (nivel1) {
      nivel1=false;
      Application.LoadLevel ("leñador");
      selectniveles.SetActive (false);
   }
   if (nivel2) {
      nivel2=false;
      Application.LoadLevel ("leñadornivel2");
   }
   if (nivel3) {
      nivel3=false;
      Application.LoadLevel ("leñadornivel3");
   }
   if (salir) {
      //salir=false; //aqui no haria falta
      Application.Quit ();
   }
   if (nivel4) {
      nivel4=false;
      Application.LoadLevel ("leñadornivel4");
   }
   if (menu) {
      menu=false;
      Application.LoadLevel ("menu");
   }
}

 
 

Cita de: kaito date=1468045967Creo que el fallo se encuentra en el script selectlevels, ya que no reinicias las variables bool a false cuando cambias de nivel. Entonces, puede producir un error al quedar una o más variables en true.
   
   
       
   
   
      Modifica esta parte de código, añadiendo un reinicio a false de la variable bool:
   
   
       
   
   

   void Update ()
{
   if (nivel1) {
      nivel1=false;
      Application.LoadLevel ("leñador");
      selectniveles.SetActive (false);
   }
   if (nivel2) {
      nivel2=false;
      Application.LoadLevel ("leñadornivel2");
   }
   if (nivel3) {
      nivel3=false;
      Application.LoadLevel ("leñadornivel3");
   }
   if (salir) {
      //salir=false; //aqui no haria falta
      Application.Quit ();
   }
   if (nivel4) {
      nivel4=false;
      Application.LoadLevel ("leñadornivel4");
   }
   if (menu) {
      menu=false;
      Application.LoadLevel ("menu");
   }
}

   
       
   


Si si que es posible , es lógico....
 
El nivel se activa y desactiva bien!!!
 
Eres un genio Kaito.
 
Pero sigue sin encontrar a los hijos ***os :)
 

Intro.singleton.SetActive(true);
Intro.singleton.FindChild("nivel2").SetActive(true);

 
me tira este error:
 

Assets/cuentarboles.cs(39,41): error CS1061: Type `UnityEngine.GameObject' does not contain a definition for `FindChild' and no extension method `FindChild' of type `UnityEngine.GameObject' could be found (are you missing a using directive or an assembly reference?)

 
 

Julio 09, 2016, 05:56:00 PM #9 Ultima modificación: Julio 09, 2016, 06:14:28 PM por pioj
Intro.singleton devuelve un GameObject, en este caso el GameObject selectniveles.
 
Y la función FindChild es del Componente Transform, y devuelve un Transform.
 
Por lo que tendremos que acceder a la propiedad heredada de Component gameObject.
 
 
 



   
      Entonces sería : Intro.singleton.transform.FindChild("nivel2").gameObject.SetActive(true);
   

[/quote]
 
 
 
Recuerda que si desactivas el GameObject padre Intro, automáticamente desactivas a los hijos/Child, por lo que no es necesario activar/desactivar nivel2.
 
 

Julio 09, 2016, 06:01:17 PM #10 Ultima modificación: Julio 09, 2016, 06:14:51 PM por pioj
Cita de: kaito date=1468079760Intro.singleton devuelve un GameObject, en este caso el GameObject selectniveles.
   
   
      Y la función FindChild es del Componente Transform, y devuelve un Transform.
   
   
      Por lo que tendremos que acceder a la propiedad heredada de Component gameObject.
   
   
       
   
   
      Entonces sería : Intro.singleton.transform.FindChild("nivel2").gameObject.SetActive(true);
   
   
       
   
   
      Recuerda que si desactivas el GameObject padre Intro, automáticamente desactivas a los hijos/Child, por lo que no es necesario activar/desactivar nivel2.
   
   
       
   


Totalmente de acuerdo con tigo Kaito, lo que he echo es No Desactivar momentaneamente el GO y asi no desactivar sus hijos.
 
De echo he probado lo que me has dicho.
 



   
      Intro.singleton.transform.FindChild("nivel2").gameObject.SetActive(true);
   

[/quote]
 
i me tira este error:
 



   
      NullReferenceException: Object reference not set to an instance of an object
   

[/quote]
 
Que si no voy mal quiere algo como:
 



   
      Private GameObject Intro;
   

[/quote]
 
Pero si pongo esto siguen los errores...diferentes...
 
 

Julio 09, 2016, 06:09:05 PM #11 Ultima modificación: Julio 09, 2016, 06:14:59 PM por pioj
Esta vez fue un error mio al pasarte el nombre de la función. La función FindChild no existe, la expresión correcta es Find:
 



   
      Intro.singleton.transform.Find("nivel2").gameObject.SetActive(true);
   

[/quote]
 
 

Cita de: kaito date=1468080545Esta vez fue un error mio al pasarte el nombre de la función. La función FindChild no existe, la expresión correcta es Find:
   
   
      Intro.singleton.transform.Find("nivel2").gameObject.SetActive(true);
   


Da un error de Null....;(
 
NullReferenceException: Object reference not set to an instance of an object
 
 

lo q hago es una variable publica para el gameobject y lo asigno desde el inspector, asi no importa si se desactiva o no, se puede referenciar... y no cosume tiempo en la busqueda

Julio 09, 2016, 06:38:45 PM #14 Ultima modificación: Julio 09, 2016, 06:53:51 PM por ramunda
Cita de: Braltor date=1468081949lo q hago es una variable publica para el gameobject y lo asigno desde el inspector, asi no importa si se desactiva o no, se puede referenciar... y no cosume tiempo en la busqueda
   


Gracias Braltor por la respuesta,
 
Quiero entender que lo que me comentas es que cree un public GameObject nivel2, por ejemplo en el GameObject maestro osea en el de el singleton y lo arrastre en el inspector? , teniendo en cuenta que esto pasara en una escena diferente a la que estoy?
 
Porque no puedo crear un Public GameObject y asignarlo en el inspector si esta en otra escena....:(
 
Madre mia me he encontrado con dificultades pero esta me esta quitando el sueño, tiene que haber una manera sencilla de activar un hijo de un GameObject que esta en singleton. :((
 
 
 
 
 
 

Etiquetas: