Está en la página 1de 19

Tour Virtual

Objetivo:
1. Armar una Demo de Tour Virtual para VR utilizando Google VR
a. Demo de Google VR (que queremos lograr)
b. Ventajas respecto a técnicas anteriores (Custom Shader y raycast).
c. Concepto y entendimiento de Materiales y Pipeline de renderización (general)
d. Concepto y entendimiento de las funciones de la API Physics de Unity3D
e. Funciones de Debug

Queremos lograr al finalizar este trabajo práctico un tour virtual a través de un departamento
utilizando imágenes 360.

Para lograrlo haremos uso de las librerías de Google VR mas un par de materiales.
Es importante conocer para qué son y para que se utilizan los materiales en Unity, como así
también las ventajas que nos ofrecen a lo largo del desarrollo. En AR y VR muchas veces es
importante optimizar y como se mencionó en clases anteriores, comenzar con la parte gráfica
es lo más fácil y donde se pueden ver resultados a corto plazo.

Por lo tanto; antes de adentrarnos en el trabajo práctico vamos a entender las bases de los
elementos que lo componen y esto es;

● Materiales
● Raycasting (Explicación y funcionamiento)

Pero vamos a comenzar con el ejemplo práctico y explicando punto por punto:

Setting up de Unity
Antes de comenzar debemos tener:

1. El proyecto en Android

2. Haber importado el paquete GoogleVRForUnity_1.130.1.unitypackage


3. Haber habilitado la opción de Virtual Reality en Player Settings y haber seleccionado la
SDK Cardboard.

Con eso configurado, podemos crear nuestra primera escena de VR.

El setup Inicial de la escena contendrá inicialmente la Main Camera y la Luz Direccional.

Ahora si comenzamos a agregar los componentes de Google VR!.

Transformar nuestra Cámara en VR.


Buscamos en los Prefabs que nos provee Google VR, el componente: GvrReticlePointer y lo
incluimos como un hijo de la cámara principal.
El componente, provee la “mira” o el “puntero” que nos permite interactuar con la escena
utilizando el botón de “input” del cardboard. Debe ser un hijo de la cámara principal, ya que de
esta forma nos aseguramos que va a seguir la mirada del usuario.

Además, modifica la mira (el aspecto de como se ve) para dar feedback al usuario de que está
apuntando a un objeto interactivo.

A la Main Camera, le agregamos de igual manera el componente


GvrPointerPhysicsRaycaster.

Este script simplemente lanza un RayCast al centro de la escena, seleccionando los objetos
que pueden ser “interactivos” (ya veremos luego cómo definir objetos “interactivos”).

Con estos pasos, podemos considerar que nuestra Cámara, pasó de ser una cámara normal a
una cámara AR.

Sin embargo vamos a hablar un poco más del concepto de “​Raycast​”​ ​mencionado unos
instantes atrás; ya que entender que es y cómo funciona nos será de utilidad para el trabajo
final (en caso de utilizar AR) y además nos servirá en cualquier proyecto que deseemos
encarar a futuro.

Raycast & Physics API en Unity.


Raycast es una API de Unity que nos provee diversas funciones para trabajar con funciones
de físicas tales como colisiones.

En el párrafo anterior mencionamos que el componente GvrPointerPhysicsRaycaster que le


agregamos a la cámara no hace más que disparar un “raycast”; que traducido al cordobés
sería ​“disparar un rayo desde un punto de origen en una dirección determinada, a una
distancia también determinada y que nos avise que encontró (o a que le pego)”.
La información completa de la API se puede encontrar en al documentación de Unity,
https://docs.unity3d.com/ScriptReference/Physics.html​ junto a sus ejemplos.

En los archivos proporcionados para el trabajo práctico se encuentra una escena


denominada Raycast con varios ejemplos de cómo funciona, sin embargo en este caso
particular nos importa la siguiente línea:

Physics​.​Raycast​(​transform​.​position​, ​transform​.​TransformDirection​(​Vector3​.​forward​),
out​ ​hit​, ​Mathf​.​Infinity​)

Eso traducido vendría a ser algo como:

Dibujar un rayo desde mi posición (transform.position), hacia donde estoy mirando


(transform.TransformDirection(Vector3.forward), al resultado de la colisión lo
guardamos en una variable hit; La distancia? infinito.

Entre otras ventajas de utilizar la API de physics se encuentra la de poder realizar las
comprobaciones en el momento que nosotros deseamos y no depender de que Unity realice
chequeos constantemente a ver que sucede.

Cable aclarar que para que el raycast funcione el elemento a colisionar debe tener un collider
asignado.

Un último elemento que nos falta asignar a la escena es el componente Gvr Pointer Input
Module al Event System.
GvrPointerInputModule
El componente provee una implementación del ​BaseInputModule​ de Google VR; el cual nos
permite interactuar no solo con objetos 3D en la escena sino también con los objetos de
interfaz.

Provee soporte para el controlador del DayDream y para los punteros de mira (Cardboard). Es
importante asociar este componente al EventSystem en la escena.

Al hacer esta operación nos permite que el un objeto que está siendo “apuntado” por el raycast
generado por GvrPointerPhysicsRaycaster pueda implementar un evento de interfaz
(EventTrigger).

Los eventos que dispara son: Enter, Exit, Down, Up, Click, Select, Deselect, UpdateSelected,
and GvrPointerHover.

EventSystem

EventSystem es el componente de Unity que se encarga de manejar o controlar los Input; y


Raycasting, enviando “mensajes de evento” al objeto al momento de detectar alguno los
eventos.

Una escena de Unity debe tener una sola instancia del EventSystem. Cuando el
EventSystem está en la escena, comienza a buscar por cualquier otro componente (asociado
al mismo GameObject que el EventSystem) que sean del tipo (hereden) de
BaseInputModule​, cuando el componente EventSystem detecta algún raycast o input,
comienza a actualizar esos scripts informando de la situación.

Es importante destacar que el orden de los componentes afecta el orden de ejecución.

Por último para poder mover la cámara en el editor, es necesario que agreguemos un
“emulador” en la escena. Google VR nos provee dentro de la carpeta Prefabs un componente
GvrEditorEmulator​.
La escena en este punto, debería verse similar a:

Agregando los “Rooms”


En los archivos del proyecto se proporcionan algunas imágenes que son las que vamos a
utilizar para simular los cuartos.

Es importante tener en cuenta ciertos factores de las imágenes que necesitamos utilizar para
crear el tour. Deben tener una relación de aspect ratio de 2:1 y proyección equirectangular
(haciendo referencia esto último al estiramiento que debe producirse en la parte superior e
inferior de la imagen).

Estas imágenes tienen que ser importadas en Unity como “Texture Shape: Cube”
Al seleccionar esta forma de textura, Unity considera la imagen como una colección de 6
texturas cuadradas, que pueden formar un cubo.
En la documentación de Unity hay más información al respecto (sobre todo para el uso de
cubemaps para mapas de reflexión): ​https://docs.unity3d.com/Manual/class-Cubemap.html​ Sin
embargo, la imagen que más nos interesa es la siguiente:

Como pueden ver, transforma la visualización de nuestra imagen de un plano 2D a una esfera
asignado distintos cuadrantes para cada parte de la misma (+/- X; +/- Y, etc).

Con esto ya tenemos lista nuestra imagen para utilizar en la escena. Sin embargo nos está
faltando algo muy importante para poder continuar y es el “Material” que nos permita utilizar
este cubemap en una Sphere de Unity.

Creación de la Esfera y Material


En nuestro proyecto, hacemos botón derecho sobre la
jerarquía y creamos nuestra esfera (3D Object -> Sphere).

Nuestra Esfera, tiene un material asignado por defecto, que


si lo desplegamos no nos da muchas opciones; y menos
aún una opción para cargar nuestra textura.

Por lo tanto vamos a proceder a crear nuestro propio


Material, que luego le asignaremos a la Esfera.
En nuestro proyecto, desplegamos la opción de Create y
seleccionamos Material.

Le asignamos un nombre que deseemos pero antes de


continuar vamos a cambiar el tipo de “Shader” que utiliza el
material.

Haciendo click sobre el recientemente creado material


seleccionamos la opción “Shader” y elegimos Skybox ->
Cubemap.

Al hacer esto, nuestro material cambio de propiedades y como verán ahora nos deja incluir
como “Textura” un cubemap (y además setear la tonalidad).
Si hacemos click sobre el cuadrado de Textura (donde dice None) Veremos que la ventana que
se abre nos permite seleccionar nuestros texturas del tipo “Cube”.

Con el material listo, volvemos a la esfera que creamos en la escena y le cambiamos el


material por el que acabamos de crear.

Es decir cambiamos de esto:

a esto:

Ponemos la esfera en la posición 0,0,0.


Ponemos nuestra MainCamera en la posición 0,0,0.
Le damos Play!

Y ya deberíamos tener una cámara que se mueve mirando alrededor de una esfera!.

Materiales, Shaders & Texturas

Materiales​ son “definiciones” acerca de cómo la superficie debería ser renderizada,


incluyendo referencias a texturas utilizadas, información del tiling, tintes de color y más. Las
opciones disponibles para un material depende en qué shader del materia está utilizando.
Shaders​ son scripts pequeños que contienen los cálculos de matemáticas y algoritmos para
calcular el color de cada pixel renderizado, basándose en el input de iluminación y la
configuración del Material.

Texturas​ son imágenes. Un material contiene referencias a texturas, para que el shader del
Material puede utilizar las texturas mientras calcula el color de la superficie de un objeto.

Entonces:
Un material especifica un shader en ser utilizado, y el shader utilizado determina qué
opciones están disponibles en el material. Un shader especifica una o más variables de
textura que espera utilizar.

El Standard Shader es el más utilizado en Unity actualmente y provee la mayoría de las


opciones necesarias para el armado correcto de una escena; sin embargo es importante
reconocer los casos en los que otros shaders son necesarios.

Datos intrínsecos de los Shaders, pero que son importantes reconocer y tener en cuenta al
momento de determinar qué shaders utilizar y cuándo es el número de pasadas, el ideal de
escena debe contener la menor cantidad de materiales y la menor cantidad de pasadas por
material.

Puedo crear mis propios Shaders?


La creación de un shader es un tema realmente complejo, sin embargo con mucha teoria y
practica se pueden lograr cosas muy buenas y sobre todo mejorar 1000% el rendimiento de
nuestro juego.

Unity nos provee una forma “Fácil” de estudiar los built-in shaders. Si seleccionamos un
material y nos vamos a la rueda de settings que aparece en la parte superior derecha de las
propiedades veremos que hay un opción “Edit Shader”.
Al hacer click nos lleva una ventana que es muy útil, por más que no estemos interesados en
modificar el shader en este momento.

Esto nos muestra un rápido overview del Shader, lo más interesante de esto, lo podemos ver
en la parte de ​Properties​ las cuales nos indican el nombre por el cual podremos acceder por
código a las propiedades del material y modificarlas!.

Por ejemplo, si revisamos el script Sphere.cs veremos lo siguiente:

Como se puede ver, logramos acceder a una propiedad del material, que se llama _Color y
cambiarle el valor mediante código.

Por otro lado la misma pantalla nos provee un botón ​“Compile and Show code”, ​donde nos
muestra el código del Shader en cuestión.
Modificar cualquier valor ahí (sin saber mucho) puede causar que rompamos todo! así que
siempre es recomendable crear una copia del Shader antes de modificarlo.

Por último en la versión 2018 de Unity ya incluyeron un editor de Shaders (similar a lo que
hacia ShaderForge), que promete simplificar mucho el trabajo de armar custom shaders!.
Teletransportandome por los Rooms
Ya hemos visto cómo crear una cámara, un room; Nos estaría faltando la parte de poder
movernos entre los diferentes rooms.

Antes de comenzar vamos a clonar nuestra esfera inicial y nuestros Materiales. Es decir vamos
a crear una esfera por Room y además vamos a crear un material por esfera (utilizando las
distintas imágenes del Panorama).

Supongamos que tenemos 2 esferas, una para el Hall y una para el Dinning; en la ventana de
jerarquía deberíamos ver algo así:

Mientras que en la ventana de proyecto deberíamos ver algo


como lo siguiente:

Es decir un material por cada esfera que vamos a utilizar.

Ahora bien, tenemos 2 formas de teletransportarnos, la primera es mover nuestra “Cámara” a


distintos puntos de la escena, entonces en nuestra escena tendríamos las distintas esferas en
diferentes posiciones.
O la forma “Lazy” de teletransportarnos que es dejar
todas las escenas en el centro de nuestro mundo
(0,0,0) y activar/desactivar cuando consideremos
necesario.

Evidentemente vamos a ir por la forma “Lazy”.

Así que vamos a tener todas nuestras esferas en la


posición 0,0,0.

A cada esfera le vamos a agregar los puntos


de escape. No nos interesa en este momento
que sea “realista”; sino funcional así que
pueden asignarlo en el lugar que quieran
MIENTRAS SEA DENTRO DE LA ESFERA!!

Creamos otro modelo 3D dentro del Hall (yo


voy a utilizar una esfera, pero pueden utilizar
lo que quieran). En mi caso tambien lo voy a
crear como hijo de nuestra “esfera” principal;
sin embargo para poder hacer uso de la “local
position”; sin embargo uds pueden crearlo
donde deseen.

Por último a la esfera recientemente creada le vamos a asignar un componente para que
capture el EventTrigger.
Add Component -> Event Trigger
Add New Event Type -> Pointer Click

Deberíamos tener entonces en el inspector algo como esto:

Ahora bien, nos estaría faltando alguien que se encargue de recibir la orden de activar y
desactivar las esferas.

En la escena creamos un nuevo GameObject (empty), con el nombre que deseen. Dejando la
escena de esta forma.

En mi caso, MainController. va a ser el Actor que va a encargarse de activar/desactivar


escenas.

Le asignamos un Script ya preparado para la ocasión. ​Scripts/MainController.cs

Y si se fijan el Script tiene como variable un “Array de GameObjects”. Simplemente arrastramos


las esferas a cada lugar del array.
Si se fijan, nuestro componente MainController.cs tiene una función pública con el nombre
MoveTo, que recibe como parámetro un valor entero. Ese valor entero es la posición en el
“Array” de la esfera que queremos mostrar.
Entonces, volvemos a nuestro punto de teletransport (el que tiene el Evento Trigger),
Seleccionamos como Componente el ​MainController​ y como función ​MoveTo ​y en el
parámetro, ponemos el valor de la escena a la cual queremos movernos.

Linkeamos de la misma forma todas las esferas. Y si hicimos todo bien y le damos play;
deberíamos poder navegar por todas las esferas.

También podría gustarte