Diferencia entre revisiones de «Unity Manejo de Objetos Gráficamente»
(Página creada con « <br> -- Ángel D. Fernández González -- (2018).») |
|||
| (No se muestran 26 ediciones intermedias del mismo usuario) | |||
| Línea 1: | Línea 1: | ||
| + | =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; | ||
| + | [[Imagen:Unity3d_gameobjects_1A.jpg|300px|center]] | ||
| + | * Todo GameObject <u>debe de tener un componente Transform</u>. | ||
| + | : Además, un GameObject puede tener componentes asociados al mismo y una jerarquía: | ||
| + | [[Imagen:Unity3d_gameobjects_2.jpg|300px|center]] | ||
| + | * 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. | ||
| + | [[Imagen:Unity3d_gameobjects_3.jpg|1000px|center]] | ||
| + | : 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,... | ||
| + | |||
| + | |||
| + | [[Imagen:Unity3d_gameobjects_1.jpg|500px|center]] | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | =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). | ||
| + | |||
| + | |||
| + | <gallery caption="Componentes de un GameObject" widths="350" heights="300px" perrow="2"> | ||
| + | Image:Unity3d_gameobjects_4.jpg| En el ejemplo podemos ver como la nave tiene un componente transform, un componente Mesh-Filter, un componente Mesh-Renderer y un Shader. Podemos añadir-asociar nuevos componentes pulsando el botón '''Add Component'''. | ||
| + | Image:Unity3d_gameobjects_5.jpg| Ahora podemos buscar escribiendo el componente que queramos o buscarlo dentro de alguna de las categorías. | ||
| + | Image:Unity3d_gameobjects_6.jpg| En el ejemplo se añadió dentro de la categoría Phisics => Box Collider. Vemos que dicho componente tiene unas propiedades que podemos modificar y además dispone de un checkbox el cual indica si queremos habilitar o no dicho componente. Al estar habilitado, un box-colider crear una 'caja' que rodea la figura 3D. | ||
| + | Image:Unity3d_gameobjects_7.jpg| Al deshabilitar el componente, deja de aplicarse al GameObject asociado y gráficamente, en este caso, la caja se 'difumina'. | ||
| + | Image:Unity3d_gameobjects_8.jpg| En esta imagen hemos añadido otro componente denominado 'RigidBody' el cual no se puede 'deshabilitar' y dispone de sus propiedades. | ||
| + | Image:Unity3d_gameobjects_9.jpg| Los componentes pueden ser cambiados de orden 'arrastrando' el componente al lugar que queramos o pulsando sobre la rueda dentada y escogiendo la opción 'Move Up' o 'Move Down'. En la imagen podemos ver como el RigidBody está antes del BoxColider al cambiarlo de sitio. El orden en principio no importa salvo en dos casos: [https://assetstore.unity.com/packages/essentials/post-processing-stack-83912 Image Effect Components] y el orden de ejecución de los scripts (si tenemos varios) ya que irán en orden de arriba-abajo. | ||
| + | Image:Unity3d_gameobjects_10.jpg| Podemos eliminar cualquier componente (menos el Transform) pulsando la rueda dentada y escogiendo la opción '''Remove Component'''. | ||
| + | </gallery> | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | |||
| + | =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. | ||
| + | <gallery caption="Creando un Empty GameObject" widths="350" heights="300px" perrow="2"> | ||
| + | Image:Unity3d_gameobjects_11.jpg| Podemos pulsar el botón derecho del ratón sobre la Hierarchy Window. | ||
| + | Image:Unity3d_gameobjects_12.jpg| Podemos presionar el botón '''Create''' de la misma ventana. | ||
| + | Image:Unity3d_gameobjects_12.jpg| O a través del menú principal. | ||
| + | </gallery> | ||
| + | |||
| + | |||
| + | * Una vez creado podemos hacer que se visualice el nombre del GameObject con un color: | ||
| + | <gallery caption="Cambiando el color a un Empty GameObject" widths="350" heights="300px" perrow="2"> | ||
| + | Image:Unity3d_gameobjects_14.jpg| Con el Empty GameObject seleccionado, presionamos en el icono del cubo de la ventana Inspect Window. | ||
| + | Image:Unity3d_gameobjects_15.jpg| Escogemos el color que queramos que tenga el nombre del GameObject. | ||
| + | Image:Unity3d_gameobjects_16.jpg| Podemos cambiar el texto asociado al gameobject que pasa a tener el color seleccionado. | ||
| + | </gallery> | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | ==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 <u>valores relativos con respecto al GameObject padre</u>. | ||
| + | : 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. | ||
| + | |||
| + | |||
| + | <gallery caption="Punto Pivot" widths="450" heights="300px" perrow="2"> | ||
| + | Image:Unity3d_rotac_10b.jpg| En nuestra escena creamos un cubo en el punto (0,0,0) y una esfera que se encuentre a su lado '''y que es hija del cubo en la jerarquía'''. | ||
| + | Image:Unity3d_rotac_10c.jpg| Si pulsamos sobre el cubo, podemos ver como se muestra el 'centro' de los dos objetos. Si ahora movemos el cubo, también se moverá la esfera. | ||
| + | Image:Unity3d_rotac_10d.jpg| Si pulsamos en el botón de 'centro' cambia a '''pivot''' y ahora aparece el punto de referencia que va a utilizar el cubo para rotar, y que también va a utilizar la esfera cuando se rote el cubo. | ||
| + | Image:Unity3d_rotac_10e.jpg| Si ahora rotáis el cubo podéis observar como rota la esfera de acuerdo al punto pivot del cubo. | ||
| + | </gallery> | ||
| + | |||
| + | |||
| + | * '''<u>Nota:</u>''' 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. | ||
| + | <gallery caption="Punto Central" widths="450" heights="300px" perrow="2"> | ||
| + | Image:Unity3d_traslac_center_1.jpg| En la ToolBar aparece el botón con 'Center' y aparece un punto situado a la misma distancia entre los dos GameObjects. | ||
| + | Image:Unity3d_traslac_center_2.jpg| Al mover dicho punto se mueven los dos GameObjects a la vez. | ||
| + | </gallery> | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | |||
| + | ==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: [https://docs.unity3d.com/ScriptReference/Transform.GetChild.html 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. | ||
| + | [[Imagen:Unity3d_gameobject_jerarquia_1.JPG|500px|center]] | ||
| + | |||
| + | : Creamos un script de nombre '''AccediendoPadre''': | ||
| + | <syntaxhighlight lang="java" line enclose="div" highlight="9"> | ||
| + | using UnityEngine; | ||
| + | |||
| + | public class AccediendoPadre : MonoBehaviour { | ||
| + | |||
| + | private Transform padreCubo; | ||
| + | |||
| + | // Use this for initialization | ||
| + | void Start () { | ||
| + | padreCubo = transform.parent; | ||
| + | } | ||
| + | |||
| + | // Update is called once per frame | ||
| + | void Update () { | ||
| + | |||
| + | if (Input.GetKey(KeyCode.W)) | ||
| + | { | ||
| + | padreCubo.transform.Translate(padreCubo.transform.forward * Time.deltaTime); | ||
| + | } | ||
| + | if (Input.GetKey(KeyCode.S)) | ||
| + | { | ||
| + | padreCubo.transform.Translate(-padreCubo.transform.forward * Time.deltaTime); | ||
| + | } | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | :* 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. | ||
| + | |||
| + | [[Imagen:Unity3d_gameobject_jerarquia_2.JPG|500px|center]] | ||
| + | |||
| + | |||
| + | : 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: | ||
| + | <syntaxhighlight lang="java" line enclose="div" highlight="10,11"> | ||
| + | ...... | ||
| + | public class AccediendoPadre : MonoBehaviour { | ||
| + | |||
| + | private Transform padreCubo; | ||
| + | |||
| + | // Use this for initialization | ||
| + | void Start () { | ||
| + | padreCubo = transform.parent; | ||
| + | |||
| + | if (padreCubo == null) { | ||
| + | enabled = false; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | : 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: | ||
| + | [[Imagen:Unity3d_gameobject_jerarquia_3.JPG|500px|center]] | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | * 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''': | ||
| + | <syntaxhighlight lang="java" line enclose="div" highlight="12-19"> | ||
| + | using System.Collections; | ||
| + | using System.Collections.Generic; | ||
| + | using UnityEngine; | ||
| + | |||
| + | public class AccediendoHijos : MonoBehaviour { | ||
| + | |||
| + | |||
| + | private Transform hijo; | ||
| + | // Use this for initialization | ||
| + | void Start() | ||
| + | { | ||
| + | for (int cont=0; cont < transform.childCount; cont++) | ||
| + | { | ||
| + | hijo = transform.GetChild(cont); | ||
| + | if (hijo.gameObject.name.Equals("Cylinder")) | ||
| + | { | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | // Update is called once per frame | ||
| + | void Update() | ||
| + | { | ||
| + | |||
| + | if (Input.GetKey(KeyCode.W)) | ||
| + | { | ||
| + | hijo.transform.Translate(hijo.transform.forward * Time.deltaTime); | ||
| + | } | ||
| + | if (Input.GetKey(KeyCode.S)) | ||
| + | { | ||
| + | hijo.transform.Translate(-hijo.transform.forward * Time.deltaTime); | ||
| + | } | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | :* 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. | ||
| + | |||
| + | [[Imagen:Unity3d_gameobject_jerarquia_4.JPG|500px|center]] | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | * '''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. | ||
| + | |||
| + | |||
| + | |||
| + | '''<u>NOTA IMPORTANTE:</u>''' 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<>() | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | |||
| + | =Diferencia entre Assets/GameObjects= | ||
| + | |||
| + | * Yo lo comenté anteriormente, pero recordar que los Assets <u>no tienen componente transform</u> 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. | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | =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. | ||
| + | |||
| + | <gallery caption="Asociando Tags a GameObjects" widths="350" heights="300px" perrow="2"> | ||
| + | Image:Unity3d_gameobject_tag_1.jpg| '''Seleccionado un GameObject''' en la ventana Inspector podemos desplegar la ventana con los Tags creados. Por defecto vienen varios. | ||
| + | Image:Unity3d_gameobject_tag_2.jpg| Si pulsamos el botón '''Add tag''' aparece la opción de crear nuevos tags pulsando el botón +. | ||
| + | Image:Unity3d_gameobject_tag_3.jpg| Al pulsar '''Save''' se guarda la nueva etiqueta que podemos eliminar pulsando el botón -. | ||
| + | Image:Unity3d_gameobject_tag_4.jpg| Ahora '''debemos de volver a seleccionar el GameObject y escoger la nueva etiqueta creada'''. | ||
| + | </gallery> | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | * Veremos el uso de etiquetas en la [http://wiki.cifprodolfoucha.es/index.php?title=Unity_Scripts sección de Scripts de esta Wiki]. | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | '''[https://wiki.cifprodolfoucha.es/index.php?title=Programacion_de_videojuegos_con_UNITY3D#UNIDAD_3:_Creando_videojuego_3D Enlace a la página principal del curso]''' | ||
| + | <br /> | ||
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] -- (2018). | <br> -- [[Usuario:angelfg|Ángel D. Fernández González]] -- (2018). | ||
Revisión actual del 14:22 19 abr 2020
Sumario
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;
- Todo GameObject debe de tener un componente Transform.
- Además, un GameObject puede tener componentes asociados al mismo y una jerarquía:
- 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.
- 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,...
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).
- Componentes de un GameObject
En el ejemplo se añadió dentro de la categoría Phisics => Box Collider. Vemos que dicho componente tiene unas propiedades que podemos modificar y además dispone de un checkbox el cual indica si queremos habilitar o no dicho componente. Al estar habilitado, un box-colider crear una 'caja' que rodea la figura 3D.
Los componentes pueden ser cambiados de orden 'arrastrando' el componente al lugar que queramos o pulsando sobre la rueda dentada y escogiendo la opción 'Move Up' o 'Move Down'. En la imagen podemos ver como el RigidBody está antes del BoxColider al cambiarlo de sitio. El orden en principio no importa salvo en dos casos: Image Effect Components y el orden de ejecución de los scripts (si tenemos varios) ya que irán en orden de arriba-abajo.
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.
- Creando un Empty GameObject
- Una vez creado podemos hacer que se visualice el nombre del GameObject con un color:
- Cambiando el color a un Empty GameObject
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.
- Punto Pivot
- 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.
- 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.
- 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.
- 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:
- 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.
- 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.
- Asociando Tags a GameObjects
- Veremos el uso de etiquetas en la sección de Scripts de esta Wiki.
Enlace a la página principal del curso
-- Ángel D. Fernández González -- (2018).