#2 Encontrar objetos de la jerarquía. FindGameObject. [Serie Fundamental de Unity]

Por GameDevTraum

Introducción

En este artículo vamos a estudiar distintas formas de encontrar, desde un Script, los GameObjects (objetos) que se encuentran en la jerarquía. Entre las formas tenemos asignar directamente los objetos desde el inspector o encontrarlos a través de métodos como “FindGameObject”.

Página principal del proyecto

Artículos de la Serie Fundamental de Unity

Antes de empezar te invito a ver el siguiente video en el que se resuelve este problema:

Procedimiento

Vamos a trabajar con la estación Find GameObjects, que consiste en 5 objetos sobre una mesa. La función de esta estación es regresar al estado de reposo a los objetos que son perturbados.

El problema es que inicialmente no tenemos las referencias de los objetos, así que la función no se puede llevar a cabo.

5 modelos 3d similares a trofeos sobre una mesa
Fig. 1: Estación para encontrar objetos en estado de reposo.

modelo 3d volcado sobre una mesa, partículas alrededor
Fig. 2: Estación para encontrar objetos perturbada. Luego de unos segundos los objetos desaparecen.

3 modelos 3d colocados sobre una mesa, partículas alrededor
Fig. 3: Estación para encontrar objetos volviendo al estado de reposo. Luego de unos segundos los objetos reaparecen en su posición inicial.

Dentro del Script “FindGameObject” tenemos algo de código ya escrito.

Fig. 4: Script FindGameObject. Definición de los objetos a encontrar.

Los 5 objetos están declarados como privados y están serializados, por eso aparecen en el inspector (como se observa en la siguiente figura).

Fig. 5: Estación para encontrar objetos en estado de reposo.

En el método Start se hace la llamada a 5 métodos que se encargarán de encontrar las referencias.

Fig. 6: Llamada a los métodos que se encargan de encontrar las referencias de los objetos.

Los métodos se encuentran incompletos. Nuestro objetivo es completarlos y descubrir distintas formas de encontrar las referencias.

Fig. 7: Métodos que se encargan de encontrar las referencias de los objetos.

Forma #1: Asignar los objetos directamente en el inspector a un campo serializado.

Como se observa en la figura 4, todos los objetos están definidos como privados y están serializados, pero esto es más que nada para que veamos en el inspector, cómo al iniciar el juego encontramos la referencia.

Para la forma 1, tomamos el objeto de la jerarquía y lo arrastramos al campo en el inspector. Como se ilustra a continuación.

Fig. 8: Asignación de GameObject a campo en la jerarquía.

Con esto ya le decimos a nuestro Script qué objeto de la jerarquía es el GameObject definido con el nombre “Object1a”.

Forma #2: Asignar los objetos directamente en el inspector a un campo público.

Esta forma es prácticamente igual que la anterior, sólo que ahora el GameObject lo definimos como público.

Fig. 9: Definición de un GameObject con visibilidad pública.

Definir un campo como público hace que sea accesible desde cualquier contexto y por lo tanto también aparece en el inspector.

Como en la forma anterior, tomamos el GameObject de la jerarquía y lo arrastramos al campo en el inspector.

Forma #3: Etiquetas. Método FindGameObjectWithTag de la clase GameObject.

La clase GameObject cuenta con un método que permite encontrar un GameObject en la jerarquía utilizando las etiquetas.

Fig. 10: Menú desplegable Tag presente en todo GameObject de la jerarquía.

Fig. 11: Ventana que aparece al hacer clic en “Add Tag” (figura 10) y luego en el signo “+”.

Luego procedemos a escribir el código necesario para encontrar el GameObject desde el Script. Vamos a escribirlo dentro del método “findGameObject2” que se ve en la figura 7.

La línea de código es la siguiente:

object2=GameObject.FindGameObjectWithTag(“Object2”);

Vamos a analizarla por partes, al escribir “object2=” estamos diciendo que el campo object2 va a valer lo que sea que coloquemos luego del signo “=”. Como se observa en la figura 9, object2 es de tipo GameObject, por lo tanto lo que coloquemos luego del signo “=” tendrá que devolver un objeto de tipo GameObject.

Al escribir “GameObject.” (GameObject punto), estamos indicando que queremos acceder a los atributos y métodos que están definidos en la clase GameObject.

Ejecutamos un método que se llama FindGameObjectWithTag” (traducido significa: “encontrar GameObject con etiqueta”), este método necesita que le ingresemos (dentro de los paréntesis) el String con la etiqueta.

Leer esto e interpretarlo es algo complicado, pero de a poco va cobrando sentido conforme vamos aprendiendo.

En el video observamos que al ejecutar el juego, logramos encontrar la referencia de object2.

En el lenguaje C# se distinguen mayúsculas y minúsculas, por lo tanto hay que respetarlas.

Forma #4: Nombre. Método Find de la clase GameObject.

Como se observa en la figura 10 arriba del menú desplegable Tag, hay un espacio con el texto “Object2”, esto es el nombre que tiene asignado el GameObject y con ese nombre aparece listado en la jerarquía.

Utilizando el método Find de la clase GameObject podemos encontrar un GameObject por su nombre, de la siguiente forma:

object3=GameObject.Find(“Object3”);

Con esta instrucción, Unity revisará la jerarquía, encontrará el objeto llamado “Object3” (si es que hay uno) y lo asignará al campo object3.

Si no hay ningún GameObject llamado “Object3” en la jerarquía, el campo object3 tendrá el valor null. Si hay más de un objeto que tiene el mismo nombre, no podemos estar seguros de que vamos a encontrar el que queremos.

Forma #5: Componente única. Método FindObjectOfType<T>.

La última forma que vamos a ver es un poco más complicada.

La clase GameObject nos permite encontrar la referencia a una componente que esté presente en la jerarquía, por ejemplo la componente Transform, Collider, RigidBody, etc.

Por supuesto, prácticamente todos los GameObjects tienen la componente Transform, entonces en principio no sería muy útil. Pero ¿Qué pasaría si la componente que nos interesa es única en la jerarquía? Es decir, sabemos que hay un solo GameObject en la jerarquía que la tiene. Esto podría servirnos, porque encontrar esa componente única es equivalente a encontrar ese GameObject.

Podría ser cualquier componente siempre que sea única, en este caso creamos un nuevo Script con el nombre: “Object4Script” y se la asignamos al GameObject de la jerarquía llamado “Object4”.

Luego escribimos el siguiente código en el método “findGameObject4” (ver figura 7).

object4=GameObject.FindObjectOfType<Object4Script>().transform.gameObject;

Primero encontramos la referencia del objeto tipo Object4Script con el método FindObjectOfType<T> de la clase GameObject, luego accedemos a su componente transform por medio del operador punto y luego a la componente gameObject. El resultado de esto lo asignamos a object4.

De esta forma logramos encontrar el GameObject a partir de una de sus componentes. Por supuesto, si hay otro GameObject que también tiene ese componente, podríamos encontrar el GameObject equivocado.