Dans le dernier post de cette série, nous avons appris à configurer Vuforia et à commencer à développer un jeu de RA à partir de rien, en adoptant une logique similaire à celle utilisée sur Pokémon GO!
Nous avons commencé le développement d'un jeu de réalité augmentée appelé Shoot the Cubes. Il est maintenant temps d'améliorer le jeu en ajoutant de l'interaction et en rendant l'expérience plus attrayante. Nous allons nous concentrer principalement sur les possibilités que Unity nous offre, en laissant de côté les spécificités de Vuforia. Expérience avec le moteur Unity n'est pas obligatoire.
Commençons à travailler sur notre jeu. Jusqu'à présent, nous avons réussi à créer une scène de réalité augmentée qui se déplace avec le périphérique de l'utilisateur. Nous allons améliorer cette application en faisant en sorte que les cubes apparaissent et volent, et en permettant au joueur de les rechercher et de les détruire avec un tir laser..
Nous avons déjà défini une position initiale du _SpawnController en fonction de la rotation de la caméra de l'appareil. Nous allons maintenant définir une zone autour de ce point où nos cubes vont apparaître. Maintenant nous mettrons à jour le SpawnScript
pour faire le _SpawnController instancier les éléments du cube avec différentes tailles et positions aléatoires, par rapport au _SpawnController.
Modifions le SpawnScript
classe, ajout de variables pour contrôler le processus de génération.
Classe publique SpawnScript: MonoBehaviour // Elément de cube destiné à engendrer public GameObject mCubeObj; // nombre de cubes à engendrer public int mTotalCubes = 10; // Il est temps de générer le flotteur public Cubes mTimeToSpawn = 1f; // conserve tous les cubes sur la scène privée GameObject [] mCubes; // définir si la position a été définie private bool mPositionSet;
Nous allons créer une coroutine appelée SpawnLoop
gérer le processus d'apparition. Il lui incombera également de définir la position initiale du _SpawnController quand le jeu commence. Notez que le Random.insideUnitSphere
Cette méthode provoque l’instanciation des cubes à des emplacements aléatoires dans une zone sphérique _SpawnManager.
Classe publique SpawnScript: MonoBehaviour // Loop Spawning elements de cube private IEnumerator SpawnLoop () // Définition de la position de ponte StartCoroutine (ChangePosition ()); return return new WaitForSeconds (0.2f); // Génération des éléments int i = 0; alors que je <= (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;
Enfin, éditez le Début()
une fonction. Assurez-vous de retirer le StartCoroutine (ChangePosition ());
ligne et remplacez-le par un appel pour démarrer la SpawnLoop
coroutine.
Classe publique SpawnScript: MonoBehaviour void Start () // Initialisation de la boucle de génération en instance StartCoroutine (SpawnLoop ()); // Initialise le tableau de cubes en fonction de // la quantité souhaitée mCubes = new GameObject [mTotalCubes];
De retour dans Unity, vous devrez créer un préfabriqué de cube à instancier par le script..
SpawnScript
zone de l'inspecteur.Maintenant, si vous appuyez sur play dans Unity et que vous exécutez le projet sur le périphérique, vous devriez voir les cubes apparaître..
Nous devons ajouter du mouvement à ces cubes pour rendre les choses plus intéressantes. Faisons tourner les cubes autour de leurs axes et sur le ARCamera. Il serait également intéressant d’ajouter un facteur aléatoire au mouvement du cube pour créer une sensation plus organique..
Faites glisser le cube Préfabriqué du Préfabriqués dossier dans la hiérarchie.
Chaque cube aura des caractéristiques aléatoires. La taille, la vitesse de rotation et le sens de rotation seront définis de manière aléatoire, en utilisant certaines références définies précédemment. Créons des variables de contrôleur et initialisons l'état du cube.
utiliser UnityEngine; using System.Collections; Classe publique CubeBehaviorScript: MonoBehaviour // Échelle Max / Min du cube, flottant public mScaleMax = 2f; flottant public mScaleMin = 0.5f; // vitesse maximale en orbite public float mOrbitMaxSpeed = 30f; // vitesse de flottement privée float mOrbitSpeed; // Point d'ancrage pour que le cube tourne autour de Transform mOrbitAnchor privé; // Orbit direction private Vector3 mOrbitDirection; // Max Cube Scale private Vector3 mCubeMaxScale; // vitesse de croissance public float mGrowingSpeed = 10f; bool privé mIsCubeScaled = false; void Start () CubeSettings (); // Définition des paramètres de cube initiaux private void CubeSettings () // définissant le point d'ancrage comme caméra principale mOrbitAnchor = Camera.main.transform; // définition de la direction de l'orbite float x = Random.Range (-1f, 1f); float y = Random.Range (-1f, 1f); float z = Random.Range (-1f, 1f); mOrbitDirection = new Vector3 (x, y, z); // définition de la vitesse mOrbitSpeed = Random.Range (5f, mOrbitMaxSpeed); // définition de l'échelle float scale = Random.Range (mScaleMin, mScaleMax); mCubeMaxScale = nouveau Vector3 (échelle, échelle, échelle); // définit l'échelle du cube sur 0, pour l'agrandir, il faut transformer.localScale = Vector3.zero;
Il est maintenant temps d'ajouter du mouvement à notre cube. Faisons-le tourner autour de lui-même et autour du ARCamera, en utilisant la vitesse aléatoire et la direction définie précédemment.
// Update est appelé une fois par image. Void Update () // met le cube en orbite et fait pivoter RotateCube (); // Fait pivoter le cube autour d'un point d'ancrage // et effectue la rotation autour de son propre axe. RotateCube () // fait pivoter le cube autour de la transformation de la caméra. RotateAround (mOrbitAnchor.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime); // tournant autour de son axe transform.Rotate (mOrbitDirection * 30 * Time.deltaTime);
Pour le rendre plus organique, le cube augmentera à partir de la taille zéro après son apparition..
// Update est appelé une fois par image. Void Update () // met le cube en orbite et fait pivoter RotateCube (); // met à l'échelle le cube si nécessaire si (! mIsCubeScaled) ScaleObj (); // Echelle l'objet de 0 à 1 espace privé privé ScaleObj () // obj croissant (transform.localScale! = MCubeMaxScale) transform.localScale = Vector3.Lerp (transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed); sinon mIsCubeScaled = true;
Ces cubes sont trop heureux voler comme ça. Nous devons les détruire avec des lasers! Créons une arme dans notre jeu et commençons à leur tirer dessus.
Le tir laser doit être connecté au ARCamera et sa rotation. Chaque fois que le joueur «tape» sur l'écran de l'appareil, un laser est tiré. Nous allons utiliser le Physique.Raycast
classe pour vérifier si le laser a touché la cible et si ainsi nous allons en retirer un peu de santé.
À l'intérieur LaserScript, nous allons utiliser un LineRenderer
pour montrer le rayon laser, en utilisant un point d’origine connecté au bas de la ARCamera. Pour obtenir le point d'origine du rayon laser - le canon du pistolet virtuel - nous allons obtenir la caméra Transformer
au moment où un laser est tiré et déplacez-le 10 unités vers le bas.
Tout d’abord, créons des variables pour contrôler les paramètres du laser et obtenir mLaserLine
.
utiliser UnityEngine; using System.Collections; Classe publique LaserScript: MonoBehaviour public float mFireRate = .5f; flottant public mFireRange = 50f; flottant public mHitForce = 100f; public int mLaserDamage = 100; // Le rendu de ligne qui représentera le Line private LaserRenderer mLaserLine; // Définit si la ligne laser montre un bool privé mLaserLineEnabled; // Durée d'affichage des lignes laser à l'écran WaitForSeconds private mLaserDuration = new WaitForSeconds (0.05f); // heure du flottement privé jusqu'au prochain feu mNextFire; // Utiliser ceci pour l'initialisation void Start () // obtenir le générateur de rendu de ligne mLaserLine = GetComponent();
La fonction responsable du tir est Feu()
. Cela sera appelé à chaque fois que le joueur appuiera sur le bouton de tir. Remarquerez que Camera.main.transform
est utilisé pour obtenir le ARCamera position et rotation et que le laser est placé 10 unités en dessous. Cela positionne le laser au bas de la caméra.
// Lance le feu vide privé Laser () // Get ARCamera Transform Transform cam = Camera.main.transform; // Définit l'heure du prochain feu mNextFire = Time.time + mFireRate; // Définit l'origine du RayCast Vector3 rayOrigin = cam.position; // Définit la position d'origine de la ligne laser // Il y aura toujours 10 unités de moins depuis l'ARCamera // Nous avons adopté cette logique pour plus de simplicité mLaserLine.SetPosition (0, transform.up * -10f);
Pour vérifier si la cible a été touchée, nous allons utiliser un Raycast
.
// Tirez sur le vide privé Laser Fire () // Conservez les informations sur le hit RaycastHit hit; // Vérifie si le RayCast a atteint quelque chose si (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) // Définit la fin de la ligne laser sur l'objet touché mLaserLine.SetPosition (1, hit.point) ; else // Définit l'enfo de la ligne laser pour transmettre la caméra // à l'aide de la plage laser mLaserLine.SetPosition (1, cam.forward * mFireRange);
Enfin, il est temps de vérifier si le bouton de tir a été enfoncé et d'appeler les effets laser lorsque le coup est tiré.
// Update est appelé une fois par image. Void Update () if (Input.GetButton ("Fire1") && Time.time> mNextFire) Fire (); private void Fire () // code antérieur supprimé pour des raisons de simplicité // Afficher le laser à l'aide d'une Coroutine StartCoroutine (LaserFx ()); // Afficher l'énumérateur privé Laser Effects LaserFx () mLaserLine.enabled = true; // Durée pendant un temps donné pour supprimer LineRenderer return return mLaserDuration; mLaserLine.enabled = false;
De retour dans Unity, nous devrons ajouter un LineRenderer
composante de la _LaserController objet.
Si vous testez le jeu maintenant, vous devriez voir un laser en train de tirer depuis le bas de l'écran. N'hésitez pas à ajouter un Source audio composant avec un effet sonore laser à _LaserController pour pimenter.
Nos lasers doivent toucher leurs cibles, infliger des dégâts et éventuellement détruire les cubes. Nous devrons ajouter un Corps rigide aux cubes, en appliquant la force et les dommages.
Maintenant, éditons le CubeBehavior
script pour créer une fonction chargée d’endommager le cube et une autre pour le détruire lorsque sa santé tombe en dessous de 0.
Classe publique CubeBehaviorScript: MonoBehaviour // Santé du cube public int mCubeHealth = 100; // Définit si le cube est Alive private bool mIsAlive = true; // Le cube a été touché // retourne 'false' lorsque le cube a été détruit bool public Hit (int hitDamage) mCubeHealth - = hitDamage; if (mCubeHealth> = 0 && mIsAlive) StartCoroutine (DestroyCube ()); retourne vrai; return false; // Destroy Cube private IEnumerator DestroyCube () mIsAlive = false; // fait disparaître le cube GetComponent() .enabled = false; // nous attendrons un peu de temps avant de détruire l'élément // c'est utile lorsque vous utilisez un type d'effet // comme un effet sonore d'explosion. // dans ce cas, nous pourrions utiliser la longueur du son comme temps d'attente renvoyé new WaitForSeconds (0.5f); Détruire (gameObject);
D'accord, le cube peut maintenant subir des dégâts et être détruit. Modifions le LaserScript
appliquer des dommages au cube. Tout ce que nous avons à faire est de changer le Feu()
fonction pour appeler le Frappé
méthode du CubeBehavior
scénario.
Classe publique LaserScript: MonoBehaviour // Déclenche le vide privé Laser Fire () // code supprimé pour des raisons de simplicité… // Vérifie si le RayCast a atteint quelque chose si (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) // Définit la fin de la ligne laser sur l'objet frappé mLaserLine.SetPosition (1, hit.point); // Obtenir que le script CubeBehavior applique des dommages à la cible CubeBehaviorScript cubeCtr = hit.collider.GetComponent(); if (cubeCtr! = null) if (hit.rigidbody! = null) // applique une force à la cible hit.rigidbody.AddForce (-hit.normal * mHitForce); // application endommage la cible cubeCtr.Hit (mLaserDamage);
Toutes nos félicitations! Notre jeu de réalité augmentée est terminé! Oui, le jeu pourrait être plus raffiné, mais les bases sont là et l'expérience globale est plutôt attrayante. Pour rendre la chose plus intéressante, vous pouvez ajouter une explosion de particules, comme je l’ai fait dans la vidéo, et en plus de cela, vous pouvez ajouter un système de partition ou même un système d’ondes avec une minuterie pour en faire un défi de plus. Les prochaines étapes sont à vous!
Nous avons créé une expérience AR intéressante en utilisant Vuforia sur Unity, mais nous avons encore beaucoup de fonctionnalités intéressantes à couvrir. Nous n’avons vu aucune des ressources les plus sophistiquées de Vuforia: cibles, Smart Terrain, Cloud, etc. Restez à l'écoute pour les prochains tutoriels, où nous couvrirons plus de ces fonctionnalités, en utilisant toujours la même approche étape par étape.
À bientôt!