Unity Spain

Post Antiguos => General (Antiguo) => Mensaje iniciado por: ftejada en Junio 27, 2017, 09:05:12 PM

Título: Problema al arrastrar Camera a variable en inspector
Publicado por: ftejada en Junio 27, 2017, 09:05:12 PM
Hola a todos!
 
Estoy haciendo un custom editor para asignar las camaras  de la escena. En el inspector le pido al usuario que diga cuantas camaras tiene en escena para que se genere varios campos donde arrastrar cada una de las camaras. Seria algo asi:
 

 
El problema es que cuando arrastro el gameobject que contiene el componente Camera, la camara nunca se asigna y siempre se queda en "none"
 
El script donde se debe almacenar cada camara tengo un Camera[] para que se puedan almacenar tantas como el usuario diga en el inspector con el campo "Numero de Camaras" que viene en la foto de arriba.
 
 
 
El codigo seria este:
 

         
[ExecuteInEditMode]
public class GestorCamaras : MonoBehaviour
{
public Camera[]         mCameras;
....
}
 
[CustomEditor(typeof(GestorCamaras))]
public class GestorCamarasInspector : Editor
{
GestorCamaras   GC;
.....
public override void OnInspectorGUI()
{
   //.....
      EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Numero de Camaras", mStyle);
            numeroCamaras = EditorGUILayout.IntField("", numeroCamaras);
            GC.mCameras = new Camera[numeroCamaras];
            EditorGUILayout.EndHorizontal();
            for (int i = 0; i < GC.mCameras.Length; i++)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Camera_" + i, mStyle);
                GC.mCameras = (Camera)EditorGUILayout.ObjectField(GC.mCameras, typeof(Camera), true);
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.Space();
                EditorGUILayout.Space();
            }
       //.....                                              
}
}

 
¿Alguien podría decirme que estoy haciendo mal?
 
 
 
Saludos y gracias por adelantado.
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: lightbug en Junio 27, 2017, 09:37:05 PM
Hola, por que tenes el
 

GC.mCameras = new Camera[numeroCamaras];

 
 
 
en el inspector GUI? no te conviene ponerlo en OnEnable?, no se si es tu problema pero me suena que cada vez que agregas la camara para el proximo refresco de la GUI se crea un arreglo nuevo pisando al anterior, proba iniciarlizarlo en On Enable o dentro del mismo target (el monobehaviour) en la definicion (por lo menos con listas podes, no recuerdo con arrays)
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: TheBullet en Junio 28, 2017, 01:07:45 AM
Diría que es lo que dice @lightbug, cada vez que se ejecuta ese código creas un nuevo array y se pierde lo que se ha guardado.
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: ftejada en Junio 28, 2017, 02:31:00 PM
Muchas gracias por responder!!
 
He estado probando toda la mañana y parece que es lo que decis, pero no se como resolver el problema.
 
Ponerlo en OnEnable() como dijo @lightbug no parece solucionar el problema ya que OnEnable() tambien se ejecuta en cada frame y me pisa el array anterior.
 
He probado con un:
 

if(numeroCamaras != GC.mCameras.Length)
{   
    GC.mCameras = new Camera[numeroCamaras];
}

 
Pero aunque ya puedo arrastrar la camara al Field del inspector y se queda almacenada, tampoco funciona del todo bien ya que cada vez que cambio el valor "numeroCamaras" los Field se resetean a "none" aunque previamente hubiese una camara asignada a alguno de los Fields. También creo que me dio algun otro funcionamiento incorrecto pero no consigo recordarlo ahora mismo.
 
Comprendo que es por lo que dice @lightbug pero he estado pensando y probando toda la mañana pero no se como hacer un codigo correcto para que funcione bien. He probado con List<> también, pero como digo, no consigo hacer bien el codigo.
 
 
 
La idea que quiero implementar es que el usuario mediante la variable "numeroCamaras" del custom_Inspector, genere tantos campos como su valor indique, para poder arrastrar cada camara a cada uno de esos campos/Fields en el custom_Inspector.
 
Estas camaras que se han arrastrado a los Fields/Campos deben almacenarse en un array/List (Me da igual uno que otro), para poder trabajar sobre ellas en tiempo de ejecución (movimiento, rotacion, etc). Evidentemente este array/List es una variable del Script:
 

[ExecuteInEditMode]
public class GestorCamaras : MonoBehaviour
{
public Camera[]         mCameras;
....
}

 
como comenté en el primer post...
 
 
 
Me vendría bien algun ejemplo de codigo. A ver si así puedo ver clara la manera de generar este codigo correctamente para mis necesidades
 
 
 
Saludos y de nuevo muchas gracias.
 
 
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: TheBullet en Junio 28, 2017, 04:17:27 PM
Cita de: ftejada date=1498653060Muchas gracias por responder!!
   
   
      He estado probando toda la mañana y parece que es lo que decis, pero no se como resolver el problema.
   
   
      Ponerlo en OnEnable() como dijo @lightbug no parece solucionar el problema ya que OnEnable() tambien se ejecuta en cada frame y me pisa el array anterior.
   
   
      He probado con un:
   
   

if(numeroCamaras != GC.mCameras.Length)
{   
    GC.mCameras = new Camera[numeroCamaras];
}

   
      Pero aunque ya puedo arrastrar la camara al Field del inspector y se queda almacenada, tampoco funciona del todo bien ya que cada vez que cambio el valor "numeroCamaras" los Field se resetean a "none" aunque previamente hubiese una camara asignada a alguno de los Fields. También creo que me dio algun otro funcionamiento incorrecto pero no consigo recordarlo ahora mismo.
   
   
      Comprendo que es por lo que dice @lightbug pero he estado pensando y probando toda la mañana pero no se como hacer un codigo correcto para que funcione bien. He probado con List<> también, pero como digo, no consigo hacer bien el codigo.
   
   
       
   
   
      La idea que quiero implementar es que el usuario mediante la variable "numeroCamaras" del custom_Inspector, genere tantos campos como su valor indique, para poder arrastrar cada camara a cada uno de esos campos/Fields en el custom_Inspector.
   
   
      Estas camaras que se han arrastrado a los Fields/Campos deben almacenarse en un array/List (Me da igual uno que otro), para poder trabajar sobre ellas en tiempo de ejecución (movimiento, rotacion, etc). Evidentemente este array/List es una variable del Script:
   
   

[ExecuteInEditMode]
public class GestorCamaras : MonoBehaviour
{
public Camera[]         mCameras;
....
}

   
      como comenté en el primer post...
   
   
       
   
   
      Me vendría bien algun ejemplo de codigo. A ver si así puedo ver clara la manera de generar este codigo correctamente para mis necesidades
   
   
       
   
   
      Saludos y de nuevo muchas gracias.
   
   
       
   


 
 
Como dijo Jack el destripador, vamos por partes XD. 
 
1- ¿Como se puede estar ejecutando OnEnable a cada frame? OnEnable solo se ejectua cuando se activa el objeto, ¿Estás activando y desactivando el objeto en cada frame o llamando OnEnable desde un Update? Puedes ponerlo en Start() y solo se ejecutará una sola vez. A parte, puedes hacer la nueva lista o array en el momento que la declaras, no hace falta hacerlo dentro de un método y me parece que al ser publico ni siquiera hace falta para utilizarlo desde el editor.
 
2- ¿Porque necesitas una variable para indicar el número de cámaras? Cuando haces publico un array o una lista puedes seleccionar el número de componentes desde el editor y tiene justo el comportamiento que estás buscando, no hace falta especificarlo con otra variable.
 
Tienes dos opciones:

- Eliminar esa variable de numero de cámaras y simplemente que el usuario arrastre o quite las cámaras que quieras, y en el for de las cámaras pones un condicional para evitar las cámaras que sean null.

- Si estás manteniendo el número de cámaras para que quede más bonito en el editor (que es lo que me parece por la captura), guarda la lista anterior antes de sobreescribirla por una nueva tipo así:
 

       if (numeroCamaras != GC.mCameras.Length)
        {
            Camera[] camTemp = GC.mCameras;
            GC.mCameras = new Camera[numeroCamaras];
            for (int i = 0; i < numeroCamaras; i++)
            {
                if (camTemp.Length > i && camTemp != null)
                    GC.mCameras = camTemp;
            }
        }

 
 
 
Saludos
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: ftejada en Junio 28, 2017, 06:50:09 PM
Cita de: TheBullet date=1498659447 
   
   
      Como dijo Jack el destripador, vamos por partes XD. 
   
   
      1- ¿Como se puede estar ejecutando OnEnable a cada frame? OnEnable solo se ejectua cuando se activa el objeto, ¿Estás activando y desactivando el objeto en cada frame o llamando OnEnable desde un Update? Puedes ponerlo en Start() y solo se ejecutará una sola vez. A parte, puedes hacer la nueva lista o array en el momento que la declaras, no hace falta hacerlo dentro de un método y me parece que al ser publico ni siquiera hace falta para utilizarlo desde el editor.
   
   
      2- ¿Porque necesitas una variable para indicar el número de cámaras? Cuando haces publico un array o una lista puedes seleccionar el número de componentes desde el editor y tiene justo el comportamiento que estás buscando, no hace falta especificarlo con otra variable.
   
   
      Tienes dos opciones:

      - Eliminar esa variable de numero de cámaras y simplemente que el usuario arrastre o quite las cámaras que quieras, y en el for de las cámaras pones un condicional para evitar las cámaras que sean null.

      - Si estás manteniendo el número de cámaras para que quede más bonito en el editor (que es lo que me parece por la captura), guarda la lista anterior antes de sobreescribirla por una nueva tipo así:
   
   

       if (numeroCamaras != GC.mCameras.Length)
        {
            Camera[] camTemp = GC.mCameras;
            GC.mCameras = new Camera[numeroCamaras];
            for (int i = 0; i < numeroCamaras; i++)
            {
                if (camTemp.Length > i && camTemp != null)
                    GC.mCameras = camTemp;
            }
        }

   
       
   
   
      Saludos
   


 
 
Gracias de nuevo por responder @TheBullet
 
Bueno el OnEnable al que me refiero es al del customEditor que estoy haciendo, ya que pensé que era al que se referia @lightbug cuando lo mencionó. Este onEnable del customEditor se ejecuta en cada frame. ¿Porqué tengo ese OnEnable() en el customEditor que estoy haciendo? Pues no lo se muy bien. He empezado a programar en el editor y me he fijado en varios codigos que he visto para ir aprendiendo.
 
No se si existen mejores formas de hacerlo que poner un OnEnable() en el customEditor...
 
Digamos que la estructura del customEditor basicamente seria algo asi:
 

[CustomEditor(typeof(GestorCamaras))]
public class GestorCamarasInspector : Editor
{
Variables varias.....
void onEnable()
{
   //Algunas cosas aquí
   GC = (GestorCamaras)target;        
        string scriptLocation = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this));
        installPath = scriptLocation.Replace("/Editor/GestorCamarasInspector.cs", "");
        inspectorGUIPath = installPath + "/Editor/InspectorTextures";
   
   // etc ....
}
public override void OnInspectorGUI()
{
   //Aqui el grueso del codigo del customEditor
   //...
}
}

 
 
 
Por otro lado no se si he conseguido explicarme bien. Si miras el codigo del primer post veras que la clase GestorCamaras contiene la variable  mCameras:
 

[ExecuteInEditMode]
public class GestorCamaras : MonoBehaviour
{
public Camera[]         mCameras;
....
}

 
Y necesito conseguir que este array cambie su tamaño dinamicamente, al cambiar el numero de camaras desde el customEditor cuando el usuario lo cambie. Y que cuando arrastre las camaras a los Fields que se han generado, se queden almacenadas las camaras en el array "mCameras" de GestorCamaras.
 
Ya que los parametros de la clase GestorCamaras van a ser modificados por el customEditor que estoy haciendo, no le veo sentido que el usuario tenga que ir a la clase GestorCamaras para poder modificar el tamaño del array y arrastrar alli las camaras. Necesito que todo se haga desde el customEditor ya que si no, no le veo mucho sentido hacer uno. Simplemente pondria publicas las variables de la clase GestorCamaras y ya está!, las modificaría desde ahí. No se si es a esto a lo que te referia en tu 2a pregunta... jeje
 
Cuando me dices esto:
 
Cita de: TheBullet date=1498659447Eliminar esa variable de numero de cámaras y simplemente que el usuario arrastre o quite las cámaras que quieras,
   


Para que el usuario pueda arrastrar una camara al customEditor necesito poder generar ese Field a donde se arrastra la camara y la verdad es que no se como hacer que aparezcan tantos Fields como numero de camaras quiera el usuario
 
He probado con el codigo que me has puesto y al darle al play al editor de Unity, la variable "numeroCamaras" del customEditor se resetea a cero y desaparecen los Fields del inspector con las camaras que habia arrastradas a ellos.
 
Quizas tenga una solucion bastante simple pero no soy capaz de verla. Y la verdad es que ando bastante perdido en este asunto y no se como gestionarlo adecuadamente...
 
Saludos
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: lightbug en Junio 28, 2017, 09:06:21 PM
Ah no lei mucho jaja pero lo que te puedo decir es que OnEnable de monobehaviour es lo primero primero que se ejecuta cuando das play, el OnEnable del customInspector se ejecuta cada vez que seleccionas el objeto (no estando seleccionado previamente), igual creo que es como dice @TheBullet, no necesitas en principio asignar un new blabla, proba ponerlo asi y arranca en cerom vos de ahi anda poniendo el tamaño.
 

public Camera[] camaras;

 
Y con listas
 

public List<Camera> camaras = new List<Camera>();

 
Acordate de que esos campos los tenes que serializar y/o a la clase creo que tambien, cada vez que recompiles y el motor deserialice/serialice te va a borrar todos los datos y arrancar reseteado.
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: TheBullet en Junio 28, 2017, 11:49:28 PM
Cita de: ftejada date=1498668609He probado con el codigo que me has puesto y al darle al play al editor de Unity, la variable "numeroCamaras" del customEditor se resetea a cero y desaparecen los Fields del inspector con las camaras que habia arrastradas a ellos.
   
   
      Quizas tenga una solucion bastante simple pero no soy capaz de verla. Y la verdad es que ando bastante perdido en este asunto y no se como gestionarlo adecuadamente...
   
      Saludos
   


 
 
La variable numeroCamaras se reseteara a 0 porque tendrás algo que la pone a 0, ese código que te he puesto no afecta para nada al número de cámaras, solo guarda las cámaras que tenias para asignarlas al nuevo array.
 
Si te es posible copia el código entero para que lo podamos ver porque si no ni idea, debería funcionar lo que he puesto.
Título: Problema al arrastrar Camera a variable en inspector
Publicado por: ftejada en Junio 29, 2017, 10:28:17 AM
Bueno me he dado cuenta que el codigo resetea la variable "numeroCamaras" cada vez que selecciono el GameObject, que contiene el script customEditor, cuando previamente tenia seleccionado otro gameObject distinto en la Hierarchy. Aparte como comenté, tambien cuando hago play.
 
Imagino que el customEditor en estas situaciones resetea todas sus variables.
 
La solucion que he encontrado para este problema es NO crear esa variable "numeroCamaras" en el customEditor sino en la clase que el customEditor modifica. Asi el valor de la variable se conserva independientemente de que le de al play o seleccione otro gameobject.
 
 
 
Supongo que me saldrán más problemas cuando vaya avanzando más en esto, pero de momento este problema queda solucionado.
 
Muchas gracias por la ayuda a ambos.
 
Saludos.