Nell'ultimo post di questa serie, abbiamo imparato come impostare Vuforia e iniziare a sviluppare un gioco AR da zero, adottando una logica simile a quella utilizzata su Pokémon GO!
Abbiamo iniziato lo sviluppo di un gioco in Realtà Aumentata chiamato Shoot the Cubes. Ora è il momento di migliorare il gioco aggiungendo interazione e rendendo l'esperienza più coinvolgente. Ci concentreremo soprattutto sulle possibilità che Unity ci offre, tralasciando le specifiche di Vuforia. L'esperienza con il motore Unity non è obbligatoria.
Iniziamo a lavorare sul nostro gioco. Finora siamo riusciti a creare una scena in Realtà Aumentata che si muove con il dispositivo dell'utente. Miglioreremo questa app facendo spawnare e volare i cubi, e permettendo al giocatore di cercare e distruggerli con un colpo laser.
Abbiamo già impostato una posizione iniziale del _SpawnController in base alla rotazione della fotocamera del dispositivo. Ora stabiliremo un'area intorno a questo punto in cui verranno generati i nostri cubi. Ora aggiorneremo il SpawnScript
fare il _SpawnController istanziare gli elementi del cubo con diverse dimensioni e posizioni casuali, rispetto al _SpawnController.
Modifichiamo il SpawnScript
classe, aggiungendo alcune variabili per controllare il processo di spawn.
classe pubblica SpawnScript: MonoBehaviour // Elemento cubo per generare pubblico GameObject mCubeObj; // Qtd di cubi da spawned public int mTotalCubes = 10; // Tempo di spawn del cubo public float mTimeToSpawn = 1f; // tieni tutti i cubi sul palco privato GameObject [] mCubes; // definisce se è stata impostata la posizione private bool mPositionSet;
Creeremo una coroutine chiamata SpawnLoop
per gestire il processo di spawn. Sarà anche responsabile di impostare la posizione iniziale del _SpawnController quando inizia il gioco. Si noti che il Random.insideUnitSphere
il metodo fa sì che i cubi vengano istanziati in posizioni casuali all'interno di un'area sferica attorno al _SpawnManager.
public class SpawnScript: MonoBehaviour // Loop spawning cube elements private IEnumerator SpawnLoop () // Definizione della posizione di spawn StartCoroutine (ChangePosition ()); yield return new WaitForSeconds (0.2f); // spawning degli elementi int i = 0; mentre io <= (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;
Infine, modifica il file Inizio()
funzione. Assicurati di rimuovere il StartCoroutine (ChangePosition ());
linea e sostituirlo con una chiamata per avviare il SpawnLoop
coroutine.
public class SpawnScript: MonoBehaviour void Start () // Inizializzazione del ciclo di spawn StartCoroutine (SpawnLoop ()); // Inizializza l'array di cubi secondo // la quantità desiderata mCubes = new GameObject [mTotalCubes];
Ora di nuovo in Unity dovrai creare un prefabbricato cubo per essere istanziato dallo script.
SpawnScript
area dell'ispettore.Ora, se premi play in Unity ed esegui il progetto sul dispositivo, dovresti vedere i cubi spawn.
Abbiamo bisogno di aggiungere movimento a quei cubi per rendere le cose più interessanti. Ruotiamo i cubetti attorno ai loro assi e sopra il ARCamera. Sarebbe anche bello aggiungere un fattore casuale al movimento del cubo per creare un'atmosfera più organica.
Trascina il Cubo Prefabbricato dal prefabbricati cartella nella gerarchia.
Ogni cubo avrà caratteristiche casuali. La dimensione, la velocità di rotazione e la direzione di rotazione saranno definite casualmente, utilizzando alcuni riferimenti precedentemente definiti. Creiamo alcune variabili del controller e inizializziamo lo stato del cubo.
usando UnityEngine; usando System.Collections; public class CubeBehaviorScript: MonoBehaviour // Cube's Max / Min scale float pubblico mScaleMax = 2f; public float mScaleMin = 0.5f; // Orbit max Speed public float mOrbitMaxSpeed = 30f; // Orbit speed private float mOrbitSpeed; // Punto di ancoraggio per il cubo per ruotare attorno alla trasformazione privata mOrbitAnchor; // Orbita in direzione privata Vector3 mOrbitDirection; // Max Cube Scale private Vector3 mCubeMaxScale; // Growing Speed public float mGrowingSpeed = 10f; private bool mIsCubeScaled = false; void Start () CubeSettings (); // Imposta le impostazioni del cubo iniziale private void CubeSettings () // definisce il punto di ancoraggio come camera principale mOrbitAnchor = Camera.main.transform; // definisce la direzione dell'orbita float x = Random.Range (-1f, 1f); float y = Random.Range (-1f, 1f); float z = Random.Range (-1f, 1f); mOrbitDirection = new Vector3 (x, y, z); // definizione della velocità mOrbitSpeed = Random.Range (5f, mOrbitMaxSpeed); // defining scale float scale = Random.Range (mScaleMin, mScaleMax); mCubeMaxScale = new Vector3 (scala, scala, scala); // imposta la scala del cubo a 0, per accrescerla cancella transform.localScale = Vector3.zero;
Ora è il momento di aggiungere qualche movimento al nostro cubo. Facciamolo ruotare su se stesso e intorno al ARCamera, utilizzando la velocità e la direzione casuali definite in precedenza.
// L'aggiornamento viene chiamato una volta per ogni frame void Update () // rende l'orbita del cubo e ruota RotateCube (); // Fa ruotare il cubo attorno a un punto di ancoraggio // e ruota attorno al proprio asse. Vuoto privato RotateCube () // ruota attorno alla telecamera transform.RotateAround (mOrbitAnchor.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime); // ruota attorno al suo asse transform.Rotate (mOrbitDirection * 30 * Time.deltaTime);
Per renderlo più organico, il cubo si scalerà dalla dimensione zero dopo che è stato generato.
// L'aggiornamento viene chiamato una volta per ogni frame void Update () // rende l'orbita del cubo e ruota RotateCube (); // ridimensiona cubo se necessario se (! mIsCubeScaled) ScaleObj (); // Scala oggetto da 0 a 1 privato vuoto ScaleObj () // crescente obj if (transform.localScale! = MCubeMaxScale) transform.localScale = Vector3.Lerp (transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed); else mIsCubeScaled = true;
Quei cubi sono troppo felici che volano in giro in quel modo. Dobbiamo distruggerli con i laser! Creiamo una pistola nel nostro gioco e iniziamo a sparare.
Il colpo laser deve essere collegato al ARCamera e la sua rotazione. Ogni volta che il giocatore "tocca" lo schermo del dispositivo, verrà sparato un laser. Useremo il Physics.Raycast
classe per verificare se il laser colpisce il bersaglio e in tal caso toglieremo un po 'di salute da esso.
Dentro LaserScript, useremo a LineRenderer
per mostrare il raggio laser, utilizzando un punto di origine collegato al fondo del ARCamera. Per ottenere il punto di origine del raggio laser, la canna della pistola virtuale, otterremo la fotocamera Trasformare
nel momento in cui viene sparato un laser e spostarlo di 10 unità verso il basso.
Innanzitutto, creiamo alcune variabili per controllare le impostazioni del laser e ottenere mLaserLine
.
usando UnityEngine; usando System.Collections; classe pubblica LaserScript: MonoBehaviour public float mFireRate = .5f; public float mFireRange = 50f; public float mHitForce = 100f; public int mLaserDamage = 100; // Line render che rappresenterà il Laser LineRenderer privato mLaserLine; // Definire se la linea laser mostra bool privato mLaserLineEnabled; // Tempo in cui le linee Laser mostrano WaitForSeconds privato sullo schermo mLaserDuration = new WaitForSeconds (0.05f); // ora del prossimo incendio privato float mNextFire; // Usa questo per l'inizializzazione void Start () // ottenendo il Line Renderer mLaserLine = GetComponent();
La funzione responsabile per lo scatto è Fuoco()
. Questo sarà chiamato ogni volta che il giocatore preme il pulsante di fuoco. Notare che Camera.main.transform
viene utilizzato per ottenere il ARCamera posizione e rotazione e che il laser è posizionato a 10 unità al di sotto di quello. Questo posiziona il laser nella parte inferiore della fotocamera.
// Shot the Laser private void Fire () // Get ARCamera Transform Transform cam = Camera.main.transform; // Definisci il tempo del prossimo incendio mNextFire = Time.time + mFireRate; // Imposta l'origine di RayCast Vector3 rayOrigin = cam.position; // Imposta la posizione di origine della linea laser // Sarà sempre 10 unità in giù dalla ARCamera // Abbiamo adottato questa logica per semplicità mLaserLine.SetPosition (0, transform.up * -10f);
Per verificare se il bersaglio è stato colpito, useremo a raycast
.
// Shot the Laser private void Fire () // Tieni premuto il hit Hit di RaycastHit; // Controlla se RayCast ha colpito qualcosa se (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) // Imposta la fine della linea laser sull'oggetto hit mLaserLine.SetPosition (1, hit.point) ; else // Imposta l'enfo della linea laser per far avanzare la telecamera // usando la gamma Laser mLaserLine.SetPosition (1, cam.forward * mFireRange);
Alla fine, è tempo di controllare se il pulsante di fuoco è stato premuto e chiamare gli effetti del laser quando viene sparato il colpo.
// L'aggiornamento viene chiamato una volta per frame void Update () if (Input.GetButton ("Fire1") && Time.time> mNextFire) Fire (); private void Fire () // codice anteriore soppresso per semplicità // Mostra il laser usando una Coroutine StartCoroutine (LaserFx ()); // Mostra gli effetti laser IEnumerator private LaserFx () mLaserLine.enabled = true; // Via per un tempo specifico per rimuovere il ritorno rendimento di LineRenderer mLaserDuration; mLaserLine.enabled = false;
Tornando a Unity dovremo aggiungere un LineRenderer
componente al _LaserController oggetto.
Se testi il gioco ora dovresti vedere un laser sparato dalla parte inferiore dello schermo. Sentiti libero di aggiungere un Sorgente Audio componente con un effetto sonoro laser a _LaserController per ravvivarlo.
I nostri laser devono colpire i loro bersagli, applicare i danni e infine distruggere i cubi. Dovremo aggiungere un Corpo rigido ai cubi, applicando forza e danno a loro.
Ora modifichiamo il CubeBehavior
script per creare una funzione responsabile dell'applicazione del danno al cubo e un altro per distruggerlo quando la salute scende al di sotto di 0.
public class CubeBehaviorScript: MonoBehaviour // Cube Health public int mCubeHealth = 100; // Definisci se il cubo è vivo. Bool privato mIsAlive = true; // Cube ha ottenuto Hit // restituisce 'false' quando il cubo è stato distrutto public bool Hit (int hitDamage) mCubeHealth - = hitDamage; if (mCubeHealth> = 0 && mIsAlive) StartCoroutine (DestroyCube ()); ritorna vero; return false; // Destroy Cube private IEnumerator DestroyCube () mIsAlive = false; // Fa in modo che il cubo scompaia GetComponent() .enabled = false; // aspetteremo un po 'di tempo prima di distruggere l'elemento // questo è utile quando si usa qualche tipo di effetto // come un effetto sonoro esplosivo. // in questo caso potremmo usare la lunghezza del suono come attesa return return new WaitForSeconds (0.5f); Destroy (gameObject);
Ok, il cubo può ora subire danni e essere distrutto. Modifichiamo il LaserScript
per applicare danni al cubo. Tutto quello che dobbiamo fare è cambiare il Fuoco()
funzione per chiamare il Colpire
metodo del CubeBehavior
copione.
public class LaserScript: MonoBehaviour // Shot the Laser private void Fire () // codice soppresso per semplicità ... // Controlla se RayCast ha colpito qualcosa se (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) // Imposta la fine della linea laser sull'oggetto colpito mLaserLine.SetPosition (1, hit.point); // Ottieni lo script CubeBehavior per applicare il danno al target CubeBehaviorScript cubeCtr = hit.collider.GetComponent(); if (cubeCtr! = null) if (hit.rigidbody! = null) // applica la forza al target hit.rigidbody.AddForce (-hit.normal * mHitForce); // applica il danno al target cubeCtr.Hit (mLaserDamage);
Congratulazioni! Il nostro gioco in Realtà Aumentata è finito! Sì, il gioco potrebbe essere più lucido, ma le basi sono lì e l'esperienza complessiva è piuttosto coinvolgente. Per renderlo più interessante potresti aggiungere un'esplosione di particelle, come quella che ho fatto nel video, e per di più potresti aggiungere un sistema di punteggio o anche un sistema a onde con un timer per renderlo più di una sfida. I prossimi passi dipendono da te!
Abbiamo creato un esperimento AR interessante con Vuforia su Unity, tuttavia abbiamo ancora molte interessanti funzionalità da trattare. Non abbiamo visto nessuna delle risorse Vuforia più sofisticate: Obiettivi, Smart Terrain, Cloud e così via. Resta sintonizzato per le prossime esercitazioni, in cui tratteremo più di queste funzionalità, sempre utilizzando lo stesso approccio passo dopo passo.
A presto!