deplacement d'objet dans coroutine

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

je suis en train de realiser un petit projet de jeu de plateau en point&click et je galere un peu pour le codage du deplacement …
En fait c'est un jeu dans lequel le plateau est represente par des cases, le joueur se deplace ainsi case par case.
Pour le faire se deplacer le long d'un chemin j'ai donc code un algorithme de aStar afin de trouver le chemin entre la case pointe par la souris et la position actuelle du joueur, celui ci etant appele dans la fonction update.
Ensuite lors du clic de la souris, si le Astar n'est pas nul, alors on appelle la fonction de mouvement du joueur, dans son controller donc une classe differente.
Et la vient le probleme … Je sais comment le deplacer en instantane sur le point d'arrive mais je voudrais pouvoir le deplacer petit a petit. J'ai donc compris qu'il fallait que je passe par les coroutines mais la c'est ma premiere utilisation de celles ci et donc du coup je m'embrouille un peu. Voici ou j'en suis :
J'arrive a faire deplacer le joueur le long du chemin trouve grace la fonction Vector3.MoveTowards() seulement le joueur ralenti petit a petit pour au final ne presque plus bouger sur la fin, ce qui n'est pas ce que je recherche. Voici mon code :

 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
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class CubeController : MonoBehaviour {
    //private List<NodeClass> aStarPath;
    public bool isMoving = false;

    public bool moveTo(List<NodeClass> aStarResult)
    {
        Debug.Log("in moveTo function");
        //this.transform.position = aStarResult[0].getNodePosition();
        for(int i = aStarResult.Count-2; i >= 0; i--)
        {
            StartCoroutine(applyMove (aStarResult[i].getNodePosition(), aStarResult[0].getNodePosition()));
        }
        return true;
    }

    IEnumerator applyMove(Vector3 goalPosition, Vector3 finalPos)
    {
        isMoving = true;
        while(true)
        {
            Vector3 currentPos = this.transform.position;
            Debug.Log("currentPos : " +currentPos); 
            if (currentPos == finalPos)
                break;
            this.transform.position = Vector3.MoveTowards(currentPos, goalPosition, Time.deltaTime);
            yield return null;
        }
        isMoving = false;
    }

aStarResult est un liste de node qui constitue le chemin a suivre. aStarResult[0] est le point d'arrive et aStarResult.Last() le point de depart.
Si vous voyez le probleme ou un meilleur moyen de faire ce que je recherche je suis preneur :)

Auteur du sujet

Bonjour, du coup je crois avoir a peu pres reussi a trouver la solution a mon probleme. En fait il etait plus intelligent de faire le loop for dans la coroutine plutot qu'en dehors. Mais maintenant je me heurte a un nouveau probleme. Ce code marche parfaitement pour le premier clic, le joueur se deplace jusqu'a sa destination en suivant le chemin trouve par le aStar, d'ailleurs ca marche aussi pour le deuxieme joueur mais juste a la fin de son mouvement le programme se mais a freeze et je dois le shutdown via le task manager … Je ne comprends pas d'ou cela vient sachant que ma coroutine est tres similaire a pas mal de chose vu sur internet ca et la. Au passage si vous avez une methode pour que le deplacement se face avec une vitesse constante plutot qu'en ralentissant a l'approche de l'arrivee je suis preneur … voici mon code :

 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
public class CubeController : MonoBehaviour {
//  private List<NodeClass> aStarPath;
    public bool isMoving = false;

    public bool moveTo(List<NodeClass> aStarResult)
    {
        Debug.Log("in moveTo function");
//
//      aStarPath = aStarResult;
        StartCoroutine(applyMove (aStarResult));
        return true;
    }

    IEnumerator applyMove(List<NodeClass> path)
    {
        isMoving = true;
        for(int i = path.Count - 2; i >= 0; i--)
        {

            while(Vector3.Distance(this.transform.position, path[i].getNodePosition()) > 0.05f)
            {
                Debug.Log("currentPos : " + this.transform.position); 
                this.transform.position = Vector3.Lerp(this.transform.position, path[i].getNodePosition(), Time.deltaTime);

                yield return null;
            }
            Debug.Log("step reached");
            yield return null;
        }
        isMoving = false;
    }

Édité par MeliMelo

Auteur du sujet

Bonjour, grace a l'aide trouve sur le forum de unity3d-france, j'ai enfin pu trouver la solution a mon probleme. voici le nouveau code :

 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
  IEnumerator applyMove(List<NodeClass> path)
  {
      isMoving = true;
      
      // distance parcourue depuis le point de départ
      float travelDistance = 0;
      
      // position de départ
      Vector3 startPosition = transform.position;
      
      // boucle sur tous les point du chemin (c'est toujours mieux de stocker le total dans une variable locale)
      for(int i = path.Count-2 , count = path.Count, lastIndex = 0 ; i >= 0; i--){
          
          // distance entre le point de départ et le point d'arrivée (node actuel, node suivant)
          float distance = Vector3.Distance(startPosition, path[i].getNodePosition());
          
          // vecteur directeur entre ces deux points
          Vector3 direction = (path[i].getNodePosition() - startPosition).normalized;
          
          // boucle tant qu'on a pas encore dépassé la position du node suivant
          while(travelDistance < distance)
          {
              
              // on avance en fonction de la vitesse de déplacement et du temps écoulé
              travelDistance += (speed * Time.deltaTime);
              
              // si on a dépassé ou atteint la position du node d'arrivée
              if(travelDistance >= distance){
                  
                  // si on est encore en chemin, 
                  if(i > lastIndex){
                      // on se positionne un peu plus loin sur le chemin 
                      // entre les deux nodes suivants, selon la distance parcourue au delà du node d'arrivée actuel
                      float distanceNext = Vector3.Distance(path[i-1].getNodePosition() , path[i].getNodePosition());
                      float ratio = (travelDistance - distance) / distanceNext;
                      
                      // si le ratio est supérieur à 1, c'est que la distance parcourue
                      // est aussi supérieur à la distance entre les deux node suivants (donc on bouge vite)
                      // cette boucle va sauter tous les nodes qu'on est censé avoir parcourus en se déplaçant
                      // à grande vitesse
                      while(ratio > 1){
                          i--;
                          if(i == lastIndex){
                              // on est arrivé au dernier node du chemin
                              transform.position = path[i].getNodePosition();
                              // sortie de la boucle
                              break;
                          }else{
                              travelDistance -= distance;
                              distance = distanceNext;
                              distanceNext = Vector3.Distance(path[i-1].getNodePosition() , path[i].getNodePosition());
                              ratio = (travelDistance - distance) / distanceNext;
                          }
                      }
                      
                      if(i == lastIndex){
                          // on est arrivé au dernier node du chemin dans le while précédent
                          break;
                      }else{
                          transform.position = Vector3.Lerp(path[i].getNodePosition() , path[i-1].getNodePosition(), ratio);
                      }
                  }else{
                      // on est arrivé au dernier node du chemin
                      transform.position = path[i].getNodePosition();
                      break;
                  }
              }else{
                  // sinon on avance en direction du point d'arrivée
                  transform.position += direction * (speed * Time.deltaTime);
              }
              
              yield return null;
          }
          
          // on retire la distance qu'il y avait à parcourir entre les deux nodes précédents
          travelDistance -= distance;
          
          // mise à jour de la position de départ pour l'itération suivante
          startPosition = path[i].getNodePosition();
      }
      isMoving = false;
  }

Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte