Bonjour a tous et bienvenu a ce petit demo sur comment integrer des Waypoint dans Unity.
Placement des waypoint dans unity
Donc le but ici est d’offrir au joueur un sphere qui pourait le guider lors des premieres parties. Ce sphere va suivre un systeme de waypoins dans unity pour suivre un chemin bien precis. Il y aura donc des points où le sphere va attendre le joueur, mais aussi des points qui ne servent que de repere pour un chemin plus long (comme sur la rampe dans la video).
Il faut donc definir le chemin que le sphere doit prendre. J’ai vulu rester simple en utilisante des GameObjects vides pour faire le parcours. le probleme est que ces waypoints ne sont pas tres visibles.
Pour y remedier, j’ai donc ajouter un petit gizmo sur un gameobject vide come ceci :
Code des waypoint
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WayPoint : MonoBehaviour { void OnDrawGizmosSelected() { Gizmos.color = Color.blue; Gizmos.DrawSphere(transform.position, 1); } } |
Cela nous permet de bien positionner notre chemin point par point. Il ne reste qu’à programmer notre sphere pour qu’il suit le waypoint dans unity.
L’idée est d’avoir une liste de ces waypoints avec la possibilité de definir si le sphere doit attendre le joueur ou pas a chaqu’un de ces points. J’ai donc créer un enum avec les deux etats (Wait et Passthrough) qui me permettront d’avoir une liste deroulante dans le UI de unity :
et une class qui peut contenir la position (transform) et l’etat du Waypoint.
voici le debut du code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public enum WayPointState { WAIT, PASSTHROUGH }; [System.Serializable] public class WayPoints { public Transform wayPoint; public WayPointState state; } public class HoloSphere : MonoBehaviour { //List of waypoints to pass through. Also has the state of the waypoint to know if we should wait for the player. public WayPoints[] wayPoints; |
On va donc ajouter chaque waypoint dans l’ordre qu’on souhaite dans le UI de Unity et preciser la nature du point. Tout ceci sera stocké dans un array qu’on peut utiliser par la suite pour parcourir le chemin.
Pour que le visuel soit plus simple, j’utilise les gizmos pour ajouter une ligne comme ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//gismis for ease of use void OnDrawGizmosSelected() { if (wayPoints.Length >1) { Gizmos.color = Color.blue; for (int i = 0; i < wayPoints.Length-1; i++) { Gizmos.DrawLine(wayPoints[i].wayPoint.position, wayPoints[i+1].wayPoint.position); Gizmos.DrawSphere(wayPoints[i].wayPoint.position, 1); } Gizmos.DrawSphere(wayPoints[wayPoints.Length-1].wayPoint.position, 1); } } |
ceux qui nous donne ceci dans le UI :
Mouvement du holosphere entre les waypoint
Pour faire bouger l’holosphere, nous alons utiliser la fonction Vector3.MoveTowards() qui prend un origine, une destination et un temps. Nous pouvons donc definir l’origine comme la position actuel de notre sphere, la destination le prochain Waypoint et la vitesse un vitesse defini multiplié par time.deltatime pour avoir un mouvement fluide (et qui ralentis avec l’effet de bullet time deja implementer).
On va donc utiliser private Vector3 targetWaypointVectorPosition; pour stocker la position du prochain waypoint à atteindre et utiliser une fonction pour definir cette position et incrementer l’index de l’array Waypoints pour tout les autres manipulations que nous avons besoin.
Il y a egalement un sphere collider qui va se declancher quand le joueur est pres du sphere (et que la sphere est en attente du joueur) :
donc sans plus atendre, voici le code complet :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum WayPointState { WAIT, PASSTHROUGH }; [System.Serializable] public class WayPoints { public Transform wayPoint; public WayPointState state; } public class HoloSphere : MonoBehaviour { //List of waypoints to pass through. Also has the state of the waypoint to know if we should wait for the player. public WayPoints[] wayPoints; private int actualWayPoint = 0; public float speed = 6f; public float damperRadius = 0.33f; private bool isMoving = false; private Vector3 targetWaypointVectorPosition; private TrailRenderer tail; public float shortTail = 0.5f; public float longTail = 5f; // Use this for initialization void Start () { gameObject.transform.position = wayPoints[actualWayPoint].wayPoint.position; targetWaypointVectorPosition = transform.position; tail = GetComponentInChildren<TrailRenderer>(); ; if(tail == null) { Debug.LogError("No trail renderer found"); } tail.time = shortTail; } // Update is called once per frame void Update () { if (isMoving == false) { //reduce the time of the trailrenderer tail.time = shortTail; //We are not moving, no need to do any checking. Just wait for the player. return; }else { tail.time = longTail; } //Have we arrived at a waiting waypoint ? if ((wayPoints[actualWayPoint].wayPoint.position - gameObject.transform.position).magnitude < damperRadius) { //Debug.Log("arrived at waypoint"); if(wayPoints[actualWayPoint].state == WayPointState.WAIT) { //We are waiting fot the player to catch up //just wait and be special !!! isMoving = false; //Set to be actualy centered on the waypoint gameObject.transform.position = wayPoints[actualWayPoint].wayPoint.position; targetWaypointVectorPosition = transform.position; return; } else if(wayPoints[actualWayPoint].state == WayPointState.PASSTHROUGH) { // We have reached a passthrough, move on SetNextWaypoint(); } else { Debug.LogError("somthing went wrong"); } } //move to next waypoint. transform.position = Vector3.MoveTowards(transform.position, targetWaypointVectorPosition, speed * Time.deltaTime); //TODO: Might have to take care of speed. maybe in the set next waypoint. We might get a speed that varies too much depending on the distance between the waypoints. } void SetNextWaypoint() { actualWayPoint += 1; if(actualWayPoint >= wayPoints.Length) { //end of line, destroy Destroy(gameObject); return; } targetWaypointVectorPosition = wayPoints[actualWayPoint].wayPoint.position; isMoving = true; } void OnTriggerEnter(Collider col) { //if the player hits the sphere and we are waitin, go to next waypoint. if(col.tag == "Player" && !isMoving) { SetNextWaypoint(); } } //gismis for ease of use void OnDrawGizmosSelected() { if (wayPoints.Length >1) { Gizmos.color = Color.blue; for (int i = 0; i < wayPoints.Length-1; i++) { Gizmos.DrawLine(wayPoints[i].wayPoint.position, wayPoints[i+1].wayPoint.position); Gizmos.DrawSphere(wayPoints[i].wayPoint.position, 1); } Gizmos.DrawSphere(wayPoints[wayPoints.Length-1].wayPoint.position, 1); } } } |