En la última publicación de esta serie, aprendimos cómo configurar Vuforia y comenzar a desarrollar un juego AR desde cero, adoptando una lógica similar a la utilizada en Pokémon GO!
Hemos iniciado el desarrollo de un juego de Realidad Aumentada llamado Shoot the Cubes. Ahora es el momento de mejorar el juego agregando interacción y haciendo que la experiencia sea más atractiva. Nos concentraremos principalmente en las posibilidades que nos brinda Unity, dejando de lado los detalles de Vuforia. La experiencia con el motor de Unity no es obligatoria..
Vamos a empezar a trabajar en nuestro juego. Hasta ahora hemos logrado crear una escena de Realidad Aumentada que se mueve con el dispositivo del usuario. Mejoraremos esta aplicación al hacer que los cubos se desarrollen y volar, y al permitir que el jugador busque y destruya con un disparo láser..
Ya hemos establecido una posición inicial de la _SpawnController Según la rotación de la cámara del dispositivo. Ahora estableceremos un área alrededor de este punto donde se reproducirán nuestros cubos. Ahora vamos a actualizar el SpawnScript
para hacer el _SpawnController crear una instancia de los elementos del cubo con diferentes tamaños y posiciones aleatorias, en relación con el _SpawnController.
Vamos a editar el SpawnScript
clase, agregando algunas variables para controlar el proceso de desove.
SpawnScript de clase pública: MonoBehaviour // Elemento de cubo para generar GameObject mCubeObj público; // Qtd de cubos que se van a generar public int mTotalCubes = 10; // Tiempo para generar los cubos public float mTimeToSpawn = 1f; // mantener todos los cubos en el escenario privado GameObject [] mCubes; // define si la posición se estableció privado bool mPositionSet;
Vamos a crear una coroutina llamada. SpawnLoop
para gestionar el proceso de desove. También será responsable de establecer la posición inicial de la _SpawnController cuando el juego comienza Tenga en cuenta que el Random.insideUnitSphere
Este método hace que los cubos se instalen en ubicaciones aleatorias dentro de un área esférica alrededor de la _SpawnManager.
clase pública SpawnScript: MonoBehaviour // Loop Spawning cube elements private IEnumerator SpawnLoop () // Definición de la posición de generación StartCoroutine (ChangePosition ()); rendimiento retorno nuevo WaitForSeconds (0.2f); // Generando los elementos int i = 0; mientras yo <= (mTotalCubes-1) ) mCubes[i] = SpawnElement(); i++; yield return new WaitForSeconds(Random.Range(mTimeToSpawn, mTimeToSpawn*3)); // Spawn a cube private GameObject SpawnElement() // spawn the element on a random position, inside a imaginary sphere GameObject cube = Instantiate(mCubeObj, (Random.insideUnitSphere*4) + transform.position, transform.rotation ) as GameObject; // define a random scale for the cube float scale = Random.Range(0.5f, 2f); // change the cube scale cube.transform.localScale = new Vector3( scale, scale, scale ); return cube;
Finalmente, edita el Comienzo()
función. Asegúrese de quitar la StartCoroutine (ChangePosition ());
línea y reemplazarlo con una llamada para iniciar el SpawnLoop
coroutine.
SpawnScript de clase pública: MonoBehaviour void Start () // Inicializando el ciclo de inicio StartCoroutine (SpawnLoop ()); // Inicializar la matriz de cubos de acuerdo con // la cantidad deseada mCubes = new GameObject [mTotalCubes];
Ahora, de vuelta en Unity, tendrá que crear un prefab de cubo para crear una instancia del script..
SpawnScript
area del inspector.Ahora, si presionas jugar en Unity y ejecutas el proyecto en el dispositivo, deberías ver el desove de los cubos..
Necesitamos agregar movimiento a esos cubos para hacer las cosas más interesantes. Rotemos los cubos alrededor de sus ejes y sobre el ARCamera. También sería genial agregar algún factor aleatorio sobre el movimiento del cubo para crear una sensación más orgánica.
Arrastrar el Cubo Prefab de la Prefabricados carpeta a la jerarquía.
Cada cubo tendrá características aleatorias. El tamaño, la velocidad de rotación y la dirección de rotación se definirán de manera aleatoria, utilizando algunas referencias definidas previamente. Vamos a crear algunas variables de controlador e inicializar el estado del cubo..
utilizando UnityEngine; utilizando System.Collections; clase pública CubeBehaviorScript: MonoBehaviour // Escala máxima / mínima de cubos public float mScaleMax = 2f; flotador público mScaleMin = 0.5f; // Orbit max Speed public float mOrbitMaxSpeed = 30f; // Orbit speed private float mOrbitSpeed; // Punto de anclaje para que el cubo gire alrededor de la transformación privada mOrbitAnchor; // Orbit direction private Vector3 mOrbitDirection; // Escala máxima de cubos Vector3 privado mCubeMaxScale; // Velocidad de crecimiento public float mGrowingSpeed = 10f; bool privado mIsCubeScaled = falso; void Start () CubeSettings (); // Establezca la configuración inicial del cubo Private void CubeSettings () // definiendo el punto de ancla como la cámara principal mOrbitAnchor = Camera.main.transform; // definiendo la dirección de la órbita float x = Random.Range (-1f, 1f); float y = Random.Range (-1f, 1f); float z = Random.Range (-1f, 1f); mOrbitDirection = nuevo Vector3 (x, y, z); // velocidad de definición mOrbitSpeed = Random.Range (5f, mOrbitMaxSpeed); // definiendo la escala float scale = Random.Range (mScaleMin, mScaleMax); mCubeMaxScale = nuevo Vector3 (escala, escala, escala); // establece la escala del cubo en 0, para que crezca lates transform.localScale = Vector3.zero;
Ahora es el momento de añadir algo de movimiento a nuestro cubo. Hagámoslo girar alrededor de sí mismo y alrededor del ARCamera, utilizando la velocidad y dirección aleatorias definidas anteriormente.
// Se llama a Update una vez por fotograma. Update () // hace que la órbita del cubo gire RotateCube (); // Hace que el cubo gire alrededor de un punto de anclaje // y gire alrededor de su propio eje privado Void RotateCube () // rote el cubo alrededor de la cámara transform.RotateAround (mOrbitAnchor.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime); // girando alrededor de su eje transform.Rotate (mOrbitDirection * 30 * Time.deltaTime);
Para hacerlo más orgánico, el cubo se escalará desde el tamaño cero una vez que se haya generado.
// Se llama a Update una vez por fotograma. Update () // hace que la órbita del cubo gire RotateCube (); // escalar el cubo si es necesario si (! mIsCubeScaled) ScaleObj (); // Escala el objeto de 0 a 1 void privado ScaleObj () // growing obj if (transform.localScale! = MCubeMaxScale) transform.localScale = Vector3.Lerp (transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed); else mIsCubeScaled = true;
Esos cubos son muy felices volando así. ¡Hay que destruirlos con láseres! Vamos a crear un arma en nuestro juego y empezar a dispararles..
El disparo láser debe estar conectado a la ARCamera y su rotación. Cada vez que el jugador toque la pantalla del dispositivo, se disparará un láser. Usaremos el Física.Raycast
clase para comprobar si el láser golpea el objetivo y si es así, le quitaremos algo de salud.
Dentro LaserScript, usaremos un LineRenderer
para mostrar el rayo láser, utilizando un punto de origen conectado a la parte inferior de la ARCamera. Para obtener el punto de origen del rayo láser, el cañón de la pistola virtual, obtendremos la cámara Transformar
En el momento en que se dispara un láser y muévelo 10 unidades hacia abajo..
Primero, vamos a crear algunas variables para controlar la configuración del láser y obtener mLaserLine
.
utilizando UnityEngine; utilizando System.Collections; clase pública LaserScript: MonoBehaviour public float mFireRate = .5f; flotador público mFireRange = 50f; flotador público mHitForce = 100f; public int mLaserDamage = 100; // Línea de representación que representará el láser privado LineRenderer mLaserLine; // Defina si la línea de láser está mostrando privado bool mLaserLineEnabled; // Hora en que las líneas del láser se muestran en la pantalla privada WaitForSeconds mLaserDuration = new WaitForSeconds (0.05f); // hora de hasta el siguiente incendio private float mNextFire; // Use esto para la inicialización void Start () // obteniendo el Line Renderer mLaserLine = GetComponent();
La función encargada de disparar es Fuego()
. Se llamará cada vez que el jugador presione el botón de disparo. Darse cuenta de Camera.main.transform
se está utilizando para obtener el ARCamera Posición y rotación y que el láser se coloca 10 unidades por debajo de eso. Esto posiciona el láser en la parte inferior de la cámara..
// Dispare el láser privado vacío Fuego () // Obtenga ARCamera Transform Transform cam = Camera.main.transform; // Defina la hora del siguiente incendio mNextFire = Time.time + mFireRate; // Establecer el origen de RayCast Vector3 rayOrigin = cam.position; // Establezca la posición de origen de la Línea Láser // Siempre será 10 unidades por debajo de ARCamera // Adoptamos esta lógica por simplicidad mLaserLine.SetPosition (0, transform.up * -10f);
Para verificar si el objetivo fue alcanzado, usaremos un Raycast
.
// Disparar el láser privado vacío Fuego () // Mantener la información del golpe RaycastHit hit; // Comprueba si el RayCast golpeó algo si (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) // Establezca el final de la línea láser en el objeto hit mLaserLine.SetPosition (1, hit.point) ; else // Establezca el enfoque de la línea de láser para avanzar la cámara // utilizando el rango de láser mLaserLine.SetPosition (1, cam.forward * mFireRange);
Por fin, es hora de verificar si se presionó el botón de disparo y llamar a los efectos del láser cuando se dispara el disparo..
// Se llama a la actualización una vez por fotograma nula Actualización () si (Input.GetButton ("Fire1") && Time.time> mNextFire) Fire (); privado vacío Vacío () // código anterior suprimido por simplicidad // Mostrar el láser usando una Coroutine StartCoroutine (LaserFx ()); // Mostrar el privado de efectos láser IEnumerator LaserFx () mLaserLine.enabled = true; // Camino durante un tiempo específico para eliminar el rendimiento de LineRenderer mLaserDuration; mLaserLine.enabled = false;
De vuelta en la unidad tendremos que añadir una LineRenderer
componente a la _LaserController objeto.
Si prueba el juego ahora, debería ver un láser disparado desde la parte inferior de la pantalla. Siéntase libre de agregar un Fuente de audio componente con un efecto de sonido láser para _LaserController para darle sabor.
Nuestros láseres necesitan golpear sus objetivos, aplicar daño y eventualmente destruir los cubos. Tendremos que añadir un Cuerpo rígido A los cubos, aplicándoles fuerza y daño..
Ahora vamos a editar el Comportamiento del cubo
script para crear una función responsable de aplicar daño al cubo y otra para destruirlo cuando la salud cae por debajo de 0.
clase pública CubeBehaviorScript: MonoBehaviour // Cube Health public int mCubeHealth = 100; // Definir si el cubo está vivo bool privado mIsAlive = true; // Cube got Hit // devuelve 'false' cuando el cubo fue destruido public bool Hit (int hitDamage) mCubeHealth - = hitDamage; if (mCubeHealth> = 0 && mIsAlive) StartCoroutine (DestroyCube ()); devuelve verdadero falso retorno; // Destroy Cube IEnumerator privado DestroyCube () mIsAlive = false; // Hacer que el cubo desaparezca GetComponent() habilitado = falso; // esperaremos un poco antes de destruir el elemento // esto es útil cuando se usa algún tipo de efecto // como un efecto de sonido de explosión. // en ese caso, podríamos usar la duración del sonido como tiempo de espera y devolver el nuevo WaitForSeconds (0.5f); Destroy (gameObject);
Bien, el cubo ahora puede tomar daño y ser destruido. Vamos a editar el LaserScript
Para aplicar daño al cubo. Todo lo que tenemos que hacer es cambiar el Fuego()
función para llamar al Golpear
método de la Comportamiento del cubo
guión.
clase pública LaserScript: MonoBehaviour // Shot the Laser private void Fire () // código suprimido por simplicidad ... // Comprueba si RayCast golpeó algo si (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) // Establezca el final de la línea láser en el objeto golpeado mLaserLine.SetPosition (1, hit.point); // Obtenga la secuencia de comandos CubeBehavior para aplicar el daño al CubeBehaviorScript de destino cubeCtr = hit.collider.GetComponent(); if (cubeCtr! = null) if (hit.rigidbody! = null) // aplica fuerza al hit hit.rigidbody.AddForce (-hit.normal * mHitForce); // aplicar daño al objetivo cubeCtr.Hit (mLaserDamage);
¡Felicidades! ¡Nuestro juego de Realidad Aumentada está terminado! Sí, el juego podría ser más pulido, pero lo básico está ahí y la experiencia en general es bastante atractiva. Para hacerlo más interesante, puedes agregar una explosión de partículas, como hice en el video, y además de eso, puedes agregar un sistema de puntaje o incluso un sistema de ondas con un temporizador para que sea más desafiante. Los siguientes pasos son tuyos!
Creamos un interesante experimento de AR usando Vuforia en Unity, sin embargo, todavía tenemos muchas características geniales que cubrir. No vimos ninguno de los recursos de Vuforia más sofisticados: objetivos, terreno inteligente, nube, etc. Manténgase atento a los siguientes tutoriales, donde cubriremos más de esas características, siempre utilizando el mismo enfoque paso a paso..
Te veo pronto!