Unity Manejo de Objetos Gráficamente

De MediaWiki
Ir a la navegación Ir a la búsqueda

Introducción

  • Un GameObject es cualquier elemento (asset) que se encuentre dentro de nuestra escena.
A nivel de programación (scripts) podemos referenciar cualquier objeto con el tipo de dato: public GameObject miGameObjet;


Unity3d gameobjects 1A.jpg
  • Todo GameObject debe de tener un componente Transform.
Además, un GameObject puede tener componentes asociados al mismo y una jerarquía:
Unity3d gameobjects 2.jpg


  • Un Asset es la representación de cualquier elemento que pueda ser utilizado en nuestro juego.
Un Asset puede obtenerse de un fichero creado fuera de Unity como un modelo 3D, un archivo de audio, una imagen o cualquier otro recurso que Unity sea capaz de importar al proyecto.
Ciertos Assets pueden ser creados directamente por Unity como los Animator Controller (para controlar diferentes animaciones), Audio Mixer (para gestionar diferentes fuentes de audio) o Render Texture (para visualizar cámaras o vídeos en una textura).
Fijarse que digo Asset y no GameObject. Un Asset non tiene componente transform, no ha sido añadido a nuestra escena.
Unity3d gameobjects 3.jpg
En la imagen se puede ver como el modelo 'Jupiter' tiene unas propiedades en la Ventana Inspector entre las que no se encuentra el componente 'Transform'.
Cuando arrastramos el modelo a la Scene, creamos un GameObject basado en el modelo.


  • Unity incorpora unos gameobjects denominados Unity-Native GameObjects.
Estos son:
  • Básicos 3D (3D Primitives)
  • Básicos 2D (2D Primitives)
  • Luces (Lights)
  • Terrenos (Terrain): Usado para crear terrenos con elevaciones del mismo.
  • Sistema de partículas (Particle Systems): Usado para crear efectos como rayos, nieve, humo y otros muchos
  • Fuentes de audio (Audio Sources): Música y efectos de sonido.
  • Zonas de reverberación (Reverb Zones): Efecto de reverberación (por ejemplo al entrar en una cueva).
  • Elementos de Interface de Usuario (UI Elements): Por ejemplo botones, cajas de texto,...


Unity3d gameobjects 1.jpg



Componentes

  • Los componentes van a estar asociados a los GameObjects.
Es una forma que tiene Unity de realizar una programación modular, reutilizando componentes (como los scripts).




Jerarquía de objetos

  • Comenté anteriormente la conveniencia/necesidad de utilizar GameObjects vacíos.
  • Conveniente ya que de esta forma podemos disponer en la escena de multitud de GameObjects agrupados en algún tipo de jerarquía que nos permita trabajar adecuadamente.
  • Necesario ya que al agrupar a los gameobjects del juego como 'hijos' de una gameobject, vamos a poder:
  • Activarlos / desactivarlos juntos.
  • Realizar operaciones de traslación-rotación-escalado que afectarán a todos los hijos a la vez.
  • Sirven como un recurso para referenciar a otros gameobjects de nuestra escena. Por ejemplo, puedo colocar un gameobject vacío como 'hijo' de un gameobject basado en un modelo importado y después colocarlo a cierta distancia. Podría hacer que la cámara siguiera a este gameobject 'vacío' para que siempre esté situado detrás del gameobject basado en el modelo.


Recordar que un gameobject vacío (empty gameobject) solo lleva un componente transform, no lleva ningún componente Mesh ya que no 'dibuja' ninguna figura.


  • Una vez creado podemos hacer que se visualice el nombre del GameObject con un color:



Pivot

  • Como comenté en otro punto, los objetos que arrastramos o creamos en la Hierarchy Window son GameObjects los cuales pueden ser dispuestos de forma jerárquica, unos 'dentro' de otros, como si fueran carpetas dentro de carpetas.
Al hacer esto, todas las propiedades 'transform' del GameObject hijo tienen unos valores relativos con respecto al GameObject padre.
Además, cualquier modificación que hagamos sobre el padre (rotar, trasladar o escala) también se reflejará en el hijo de la misma forma.
  • En todos los objetos 3D existe un punto denominado Pivot que indica al punto de referencia para rotar/mover dicho objeto.
Normalmente este punto se encuentra en el centro del objeto 3D, pero no siempre es así.
Cuando importamos modelos complejos formados por múltiples figuras 3D puede ser que cada figura individual (imaginar un tanque con su torreta, o un avión con sus hélices, ruedas y ametralladoras) tenga su pivot en otro punto. En ese caso, cuando intentemos rotar, la rotación no la hará con respecto al punto que pensamos, sino con respecto a su pivot.
El pivot lo establece el diseñador gráfico con el programa 3D que haya utilizado.



  • Nota: Recordar por tanto que cuando trabéis con modelos importados, si cuando vayáis a realizar una rotación, el modelo no rota según lo esperado, comprobar donde se encuentra su pivot.


  • En la traslación pasa lo mismo.
Podemos seleccionar como punto 'base' para mover varios GameObjects el pivot de uno de ellos o si pulsamos sobre el botón de la ToolBar y pasamos a 'Center' aparecer un punto central.



Accediendo a los Transform-GameObject de la jerarquía

  • Cuando un script está asociado a un GameObject, podemos acceder al Transform de su GameObject padre o al transform de sus GameObjects hijos (si los tuviera).
  • Acceder al transform padre: transform.parent
  • Acceder al transform de sus hijos en la jerarquía: Transform GetChild(int index) siendo index un número que irá desde 0 hasta el número de hijos que tenga.


  • Veamos un ejemplo.
Creamos la siguiente escena en la que disponemos de un EmptyGame Object situado en (0,0,0) de nombre 'AccediendoJerarquia'.
Dentro del mismo tenemos un cubo y un cilindro, separados.
Como hijo del cubo en la jerarquía colocamos una esfera.
Unity3d gameobject jerarquia 1.JPG
Creamos un script de nombre AccediendoPadre:
 1 using UnityEngine;
 2 
 3 public class AccediendoPadre : MonoBehaviour {
 4 
 5     private Transform padreCubo;
 6 
 7 	// Use this for initialization
 8 	void Start () {
 9         padreCubo = transform.parent;	
10 	}
11 	
12 	// Update is called once per frame
13 	void Update () {
14 		
15         if (Input.GetKey(KeyCode.W))
16         {
17             padreCubo.transform.Translate(padreCubo.transform.forward * Time.deltaTime);
18         }
19         if (Input.GetKey(KeyCode.S))
20         {
21             padreCubo.transform.Translate(-padreCubo.transform.forward * Time.deltaTime);
22         }
23 
24     }
25 }
  • Línea 9: Guardamos en una variable local, el componente 'Transform' del padre en la jerarquía.
Como este script lo vamos a asociar a la esfera, en padre en la jerarquía es el Cubo.
Unity3d gameobject jerarquia 2.JPG


Si ejecutamos el juego y pulsamos las teclas W o S, podemos ver como el Cubo y la Esfera se desplazan, ya que al desplazar el Cubo, se desplazan todos sus hijos (en este caso la esfera).
  • Indicar que siempre es mejor comprobar si la referencia existe antes de operar con ella a no ser que estemos seguros de que vamos a disponer de ella.
Para comprobar si existe o no, tenemos que realizar una comparación con el valor null de la forma:
 1 ......
 2 public class AccediendoPadre : MonoBehaviour {
 3 
 4     private Transform padreCubo;
 5 
 6 	// Use this for initialization
 7 	void Start () {
 8           padreCubo = transform.parent;	
 9 
10           if (padreCubo == null) {
11             enabled = false;
12           }
13         }
En este caso, si la referencia no existe, el script se deshabilita, pero como programadores podríamos implementar otra solución.


En el ejemplo, si asociamos el script al Empty GameObject, este no tiene padre en la jerarquía, por lo que el Script se deshabilita:
Unity3d gameobject jerarquia 3.JPG



  • El proceso contrario consiste en a partir de un 'padre' acceder a los transforms de sus hijos.
Para ello es necesario hacer uso de una estructura repetitiva que utilice un contador desde el número 0 hasta transform.childCount.
Veamos un ejemplo.
Modificamos el ejemplo anterior:
  • Deshabilitamos el script 'AccediendoPadre'.
  • Creamos un nuevo script de nombre 'AccediendoHijos' y asociamos el script al Empty GameObject de nombre AccediendoJerarquia:
 1 using System.Collections;
 2 using System.Collections.Generic;
 3 using UnityEngine;
 4 
 5 public class AccediendoHijos : MonoBehaviour {
 6 
 7 
 8     private Transform hijo;
 9     // Use this for initialization
10     void Start()
11     {
12         for (int cont=0; cont < transform.childCount; cont++)
13         {
14             hijo = transform.GetChild(cont);
15             if (hijo.gameObject.name.Equals("Cylinder"))
16             {
17                 break;
18             }
19         }
20 
21     }
22 
23     // Update is called once per frame
24     void Update()
25     {
26 
27         if (Input.GetKey(KeyCode.W))
28         {
29             hijo.transform.Translate(hijo.transform.forward * Time.deltaTime);
30         }
31         if (Input.GetKey(KeyCode.S))
32         {
33             hijo.transform.Translate(-hijo.transform.forward * Time.deltaTime);
34         }
35 
36     }
37 }
  • Líneas 12-19:
  • Línea 12: Crea una variable cont que va a tener como valores los números 0 hasta el número de hijos que tenga el gameobject asociado al script.
  • Línea 14: Obtiene una referencia al Transform de cada uno de los hijos en la jerarquía.
  • Línea 15: Accedemos al GameObject asociado al transform (en este caso el transform del hijo) y comprobamos si su nombre es 'Cylinder'
  • Linea 17: En caso de que ese sea su nombre salimos de la estructura repetitiva.
El resto del código es igual al script anterior, pero esta vez movemos solo el hijo.
Al igual que en el caso anterior habría que comprobar si la referencia al transform del hijo existe antes de realizar cualquier operación con la misma.
Unity3d gameobject jerarquia 4.JPG




  • Accediendo a los GameObject
A través de los transforms podemos acceder a los GameObjects a los cuales pertenecen de la forma: transform.gameObject.


Indicar que podemos movernos en la jerarquía como queramos, por ejemplo, esta línea: transform.parent.parent obtendría el componente Transform del padre del padre del GameObject donde estuviera asociado este script.


NOTA IMPORTANTE: Indicar que a través del transform podemos acceder al GameObject asociado al mismo, mediante la propiedad 'gameObject', a la forma:

  • transform.parent.gameObject
  • transform.getChild(0).gameObject
De esta forma podes acceder al GameObject y a todos los componentes asociados al mismo, mediante la llamada al método getComponent<>()



Diferencia entre Assets/GameObjects

  • Yo lo comenté anteriormente, pero recordar que los Assets no tienen componente transform asociado.
  • Un asset es cualquier elemento que pueda ser utilizado en nuestro juego.
Un asset puede provenir de un modelo 3D creado con una herramienta externa a Unity, como Blender, un fichero de audio, una imagen, o cualquier otro tipo de recurso que pueda ser incorporado por Unity al juego. Unity también permite crear ciertos assets propios como el AnimatorController o el AudioMixed.
Los assets están situados en la Project Window.


  • Un GameObject es un asset situado en la escena.




Tags en GameObjects

  • Unity permite 'asociar' a los GameObjects una etiqueta la cual puede ser empleada posteriormente en operaciones para:
  • Buscar GameObjects en base a un nombre de Tag dado. Esto permite que un script pueda obtener una referencia a un GameObject durante la ejecución.
  • En el uso de Colliders, para identificar el GameObject que provocó el choque con otro.





Enlace a la página principal del curso



-- Ángel D. Fernández González -- (2018).