Diferencia entre revisiones de «Unity Manejo de Objetos Gráficamente»
(→Pivot) |
|||
Línea 95: | Línea 95: | ||
* 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. | * 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. | + | : 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. | : 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. | ||
Línea 125: | Línea 125: | ||
<br /> | <br /> | ||
+ | |||
==Accediendo a los Transform-GameObject de la jerarquía== | ==Accediendo a los Transform-GameObject de la jerarquía== | ||
Revisión del 14:45 10 abr 2019
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).
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.
- 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.
- 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.
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.
- Veremos el uso de etiquetas en la sección de Scripts de esta Wiki.
-- Ángel D. Fernández González -- (2018).