Dofus Battle Arena

Jeu de plateau 3D (inspire de Dofus)

a marqué ce sujet comme résolu.

Ok tres bien j'ai mis ca en place et ca marche nikel.

De plus j'ai rajoute une petite condition dans le test du raycast pour anticiper la partie "points de mouvement". En gros si le point d'impact est a plus de 3 cases du player alors on highlight pas la case et du coup impossible de se deplacer jusqu'a cette case.

Le 3 sera remplace par les points de mouvement effectif du joueur plus tard mais c'etait juste pour mettre une limite parce que la le joueur pouvait partir a l'autre bout de la map en 1 coup sans complexe. A noter que le pathfinding n'est toujours pas code pour le moment, les deplacements s'effectuent a coup de teleportation.

EDIT : Bon voila je viens de commencer mon algo de Astar et je voudrais savoir ce que vous en pensiez (si c'est totalement degueulasse ou pas) :

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

public class AstarScript : MonoBehaviour {
    private Vector3 currentPosition;
    private Vector3 arrivalPosition;
    private List<Vector3> openList;
    private List<Vector3> closeList;

    // Use this for initialization
    void Start () {
        openList = new List<Vector3> ();
        closeList = new List<Vector3>();

    }

    // Update is called once per frame
    void Update () {

    }

    public void init (Vector3 currPosition, Vector3 arrPosition)
    {
        currentPosition = currPosition;
        arrivalPosition = arrPosition;

        openList.Add(currentPosition);
        closeList.Clear();

        Astar ();
    }

    private void Astar()
    {
        int cheapestElementIndex;
        int cheapestElementCost;

        bool checkBool = computeCosts (out cheapestElementIndex, out cheapestElementCost);

        closeList.Add (openList [cheapestElementIndex]);
        openList.RemoveAt (cheapestElementIndex);
    }

    private bool computeCosts (out int cheapestIndex, out int cheapestCost)
    {
        int h;              //heuristic from element to arrivalPostion
        int g;              //cost of movement from currentPosition to element
        int f;              //cost of path from currentPosition to arrivalPosition going through element

        for (int i = 0; i < openList.Count; i++)
        {
            //heuristic is equal to manhattan distance
            h = (int) Mathf.Abs(arrivalPosition.x - openList[i].x) + Mathf.Abs(arrivalPosition.z - openList[i].z);
            //corst of movement if equal to 1 since every movement have the same weight (might change later)
            g = 1;
            //cost of path is equal to addition of heuristic and cost of movement
            f = h + g;
            //if it is the first element we check or if it is cheaper than previous ones
            if(cheapestCost == null || f < cheapestCost)
            {
                //then we store its cost and its index
                cheapestCost = f;
                cheapestIndex = i;
            }
        }
    }
}

a savoir que pour ma fonction computeCosts je suis pas bien sur de l'utilite de renvoyer un bool mais j'ai vu que c'etait pas mal utilise sur les fonctions avec des parametres out … (j'avoue ne pas trop maitriser cet aspect du c#) De meme pour les List c'est a peut pret le premier programme dans lequel je les utilise en C# et deja en C++ je maitrisais pas vraiment le concept alors bon :/

EDIT 2 : bon apparemment je n'ai pas pige le concept des parametres out puisque je me tape une erreur Assets/Scripts/AstarScript.cs(60,28): error CS0269: Use of unassigned out parameter `cheapestCost'

De plus j'ai un soucis avec mon cast sur l'attribution de la valeur a h : Assets/Scripts/AstarScript.cs(54,25): error CS0266: Cannot implicitly convert type float' toint'. An explicit conversion exists (are you missing a cast?)

J'avoue ne pas comprendre puisque justement je fais le cast …

EDIT 3 : bon ok pour le cast je suis un boloss, j'ai remplace le cast (int) en System.Convert.ToInt32() et ca marche nikel. Je savais pas que ce type de cast ne marchait pas en C# mais bon je le saurai pour la prochaine fois. Par contre toujours pas de solution pour l'autre erreur

EDIT 4 : toujours aussi con … fallait juste instancier les variables out dans la fonction tout simplement …

 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
  private void Astar()
  {
      int cheapestElementIndex;
      int cheapestElementCost;

      bool checkBool = computeCosts (out cheapestElementIndex, out cheapestElementCost);

      closeList.Add (openList [cheapestElementIndex]);
      openList.RemoveAt (cheapestElementIndex);
  }

  private bool computeCosts (out int cheapestIndex, out int cheapestCost)
  {
      int h;              //heuristic from element to arrivalPostion
      int g;              //cost of movement from currentPosition to element
      int f;              //cost of path from currentPosition to arrivalPosition going |through element
      cheapestCost = System.Convert.ToInt32(Mathf.Infinity);
      cheapestIndex = System.Convert.ToInt32(Mathf.Infinity);

      for (int i = 0; i < openList.Count; i++)
      {
          //heuristic is equal to manhattan distance
          h = System.Convert.ToInt32(Mathf.Abs(arrivalPosition.x - openList[i].x) + |Mathf.Abs(arrivalPosition.z - openList[i].z));
          //corst of movement if equal to 1 since every movement have the same weight (might |change later)
          g = 1;
          //cost of path is equal to addition of heuristic and cost of movement
          f = h + g;
          //it is cheaper than previous ones
          if(f < cheapestCost)
          {
              //then we store its cost and its index
              cheapestCost = f;
              cheapestIndex = i;
          }
      }
      return true;
  }

Salut,

Je n'ai pas encore tout regarder mais pourquoi faire ça à partir d'un MonoBehaviour ? As-tu besoin des infos propres à un GameObject, comme son Collider ou son Transform ? Idem, ici le Start fait juste office de contructeur et l'update ne sert a rien.

Dans Unity, tu n'a qu'une seule façon de faire tourner un script au Run-Time. C'est de l'attacher à un GameObject. Pour cela il faut que ton script hérite de MonoBehaviour (il possedera donc tout ce qu'il faut pour interagir avec le GameObject).

Dans le cas de ton A* il serait peut etre plus judicieux de le considérer comme une simple classe utilitaire et non comme un GameObject. Dans l'idéal l'A* serait contenue par un objet MonoBehaviour comme le gestionnaire de tour. Tu vois ce que je veux dire ? Ce sera simplement un membre en private de ton gestionnaire de tour mais ne sera pas un MonoBehaviour (et donc pas d'objet inutile avec un Update dans ta scene)

Exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class AStar
{
     ...
}

public class TurnManager : MonoBehaviour 
{
    private AStar astar;

    ...
}

Sinon pour le 'out' il faut obligatoirement que ta variable soit affectée à une valeur. Dans ton ancien code c'était bien le cas mais uniquement si ca passe par le if, donc le compilo n'aime pas. Comme tu l'as fais, la soluce était simplement de les initialiser.

Et pour le cast à la manière C. Ca devrait marcher je l'utilise tout le temps. Il y a surement une petit subtilité qui t'as échappé (c'est un peu moins souple qu'en C/C++).

+0 -0

pourquoi faire ça à partir d'un MonoBehaviour ?

aucun idee, simplement parce que les scripts que l'ont cree dans unity heritent (je sais pas si c'est le bon terme) directement de MonoBehavior sans rien demander du coup j'ai jamais trop cherche a changer ca.

Du coup je vais voir pour virer ca effectivement car aucun interet de le garder. De plus je me demandais si il serait pas interessant de creer une classe Node pour ma closeList et openList ? Une classe contenant les coordonnees du node, son parent, son g, son h, son f, etc …

Bref je vais implementer tout ca et je verrai bien ce que ca donne. Apres en soit j'ai pas besoin d'heriter de MonoBehavior pour plein de classes au final. En quoi ma classe CountTour en a besoin ?

EDIT : attends par contre j'ai pas tout capte. Tu fais 2 classes dans le meme fichier .cs ? Avec l'habitude des autres langages ca me parait bizarre mais si tu me dis que c'est correct en c# alors je ferai comme ca. Au passage c'etait de la connerie je pense cette fonction avec des parametre out. Je sais pas ce que vous en pensez mais mettre les 2 parametres en global dans la classe me parait plus simple et comme je vais de toutes facons les reutiliser dans d'autres fonction de la classe ca me semble plus judicieux.

Bon je trouve que j'ai pas mal avance aujourd'hui. J'ai donc cree la classe astar qui n'herite pas de monobehavior ainsi que NodeClass pour stocker les infos de mes differents nodes.

Il me semble avoir ete au bout de l'algo mais cependant il n'a pas l'air de marcher haha. Je poste tout de meme mon code au cas ou vous verriez directement le soucis sinon je m'y pencherai un peu plus en detail ce soir ou demain.

class AstarScript :

  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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class AstarScript {
    private Vector3 currentPosition;            //position the player
    private Vector3 arrivalPosition;            //position the algorithme will try to reach
    private List<NodeClass> openList;           //list of nodes the algorithme will analyze
    private List<NodeClass> closeList;          //list of nodes the algorithme has already analyzed
    private NodeClass node;                     //node to put all infos about one case together and then add it to the openList
    private int cheapestElementIndex;           //int used to store the index of the cheapest element of the openList
    private int cheapestElementCost;            //int used to store the cost of the cheapest element of the openList
    private Vector3[] movement = new [] {Vector3.forward, Vector3.back, Vector3.left, Vector3.right};

    //function called to initialize the algorithme
    public void init (Vector3 currPosition, Vector3 arrPosition)
    {
        //initialization of the variables
        openList = new List<NodeClass> ();
        closeList = new List<NodeClass>();
        currentPosition = currPosition;
        arrivalPosition = arrPosition;

        //gathering of the starting point informations
        node = new NodeClass (currentPosition);

        //make sure the openList and the closeList are empty at the beginning of the algorithme
        openList.Clear ();
        closeList.Clear();

        //add it to the openList
        openList.Add(node);

        //launch of the algorithme
        Astar ();
    }

    //main function of the algorithme
    private void Astar()
    {
        //while the openList is not empty
        do 
        {
            //find the cheapest element in the openList
            bool checkBool = findCheapestInOpenList ();

            //add it to the closeList and remove it from the openList
            closeList.Add (openList [cheapestElementIndex]);
            openList.RemoveAt (cheapestElementIndex);
            //if it is the arrivalPosition then stop the algorithme
            if (closeList.Last ().getPosition () == arrivalPosition)
            {
                Debug.Log ("Found solution : " + closeList.Last ().getPosition ());
                break;
            }
            else 
            {
                Debug.Log("closeList last : " + closeList.Last().getPosition());
                //else develop its children
                developChildren ();
            }
        } while(openList.Count != 0);


    }

    //develop children of the last element in the closeList
    private void developChildren()
    {
        bool[] allowMov;
        //fill the table to know which movements are allowed or not
        allowMov = checkRay ();
        //then compute informations for all children allowed
        computeCostsChildren (allowMov);

    }

    //find the cheapest element in the openList
    private bool findCheapestInOpenList ()
    {
        int h;              //heuristic from element to arrivalPostion
        int g;              //cost of movement from currentPosition to element
        int f;              //cost of path from currentPosition to arrivalPosition going through element
        cheapestElementCost = 1000;         //set the cheapest cost to 1000 to start then algo
        cheapestElementIndex = 1000;        //set the cheapest index to 1000 (not usefull)

        //watch every element in the openList
        for (int i = 0; i < openList.Count; i++)
        {
            //compute informations about the element
            //heuristic is equal to manhattan distance
            h = System.Convert.ToInt32(Mathf.Abs(arrivalPosition.x - openList[i].getPosition().x) + Mathf.Abs(arrivalPosition.z - openList[i].getPosition().z));
            openList[i].setH(h);
            //every movements cost 1 so G is just the number of movements made to get from the currentPosition to this case
            g = openList[i].getParentG() +1;
            openList[i].setG(g);
            //cost of path is equal to addition of heuristic and cost of movement
            f = h + g;
            openList[i].setF(f);

            //if it is cheaper than previous ones
            if(openList[i].getF() < cheapestElementCost)
            {
                //then we store its cost and its index
                cheapestElementCost = openList[i].getF();
                cheapestElementIndex = i;
            }
        }
        return true;
    }

    //compute informations of children ofthe last element of the closeList
    private bool computeCostsChildren (bool[] allowMov)
    {
        int h;              //heuristic from element to arrivalPostion
        int g;              //cost of movement from currentPosition to element
        int f;              //cost of path from currentPosition to arrivalPosition going through element

        //watch every movement
        for (int i = 0; i < allowMov.Length; i++)
        {
            //heuristic is equal to manhattan distance
            h = System.Convert.ToInt32(Mathf.Abs(arrivalPosition.x - closeList.Last().getPosition().x) + Mathf.Abs(arrivalPosition.z - closeList.Last().getPosition().z));
            //every movements cost 1 so G is just the number of movements made to get from the currentPosition to this case
            g = closeList.Last().getParentG() +1;
            //cost of path is equal to addition of heuristic and cost of movement
            f = h + g;
            //gather all the informations of the element in the node structure
            node.setNodePosition(closeList.Last().getPosition() + movement[i]);
            node.setH(h);
            node.setG(g);
            node.setF(f);
            node.setParentG(closeList.Last().getG());
            node.setParent(closeList.Last().getPosition());

            //if the movement is allowed and the node is not already in the openList or in the closeList
            if(allowMov[i] == true && openList.Contains(node) == false && closeList.Contains(node) == false)
            {
                //then add it to the openList
                openList.Add(node);
            }
        }
        return true;
    }

    //check if the movements are possible or not
    private bool[] checkRay ()
    {
        //RaycastHit used to collect info about the collision
        RaycastHit hit;
        bool[] allowMovement =  new [] {true, true, true, true};

        //watch every element of the table
        for (int i = 0; i < allowMovement.Length; i++)
        {
                        //Ray used to test if there is any collision on the left
                        Ray collisionRay = new Ray (closeList.Last ().getPosition (), movement [i]);

                        //Check if there is collision between the ray and any element and check if the tag is "EnvElement", if yes then don't allow the movement
                        if (Physics.Raycast (collisionRay, out hit, 1f) && (hit.collider.tag == "EnvElement" || hit.collider.tag == "Player"))
                                allowMovement [i] = false;
        }

        return allowMovement;
    }
}

class NodeClass :

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

public class NodeClass {

    private Vector3 nodePosition;
    private Vector3 parent;
    private int parentG;
    private int h;
    private int g;
    private int f;

    public NodeClass(Vector3 position)
    {
        nodePosition = position;
        parentG = 0;
    }

/* -----------------------------------------------------*/

    public void setNodePosition(Vector3 value)
    {
        nodePosition = value;
    }

    public void setParent(Vector3 value)
    {
        parent = value;
    }

    public void setParentG(int value)
    {
        parentG = value;
    }

    public void setF(int value)
    {
        f = value;
    }

    public void setG(int value)
    {
        g = value;
    }

    public void setH(int value)
    {
        h = value;
    }

    public Vector3 getNodePosition()
    {
        return nodePosition;
    }

    public Vector3 getParent()
    {
        return parent;
    }

    public int getParentG()
    {
        return parentG;
    }

    public Vector3 getPosition()
    {
        return nodePosition;
    }

    public int getH()
    {
        return h;
    }

    public int getG()
    {
        return g;
    }

    public int getF()
    {
        return f;
    }
}

la ligne : Debug.Log("closeList last : " + closeList.Last().getPosition()); qui se trouve dans la boucle while de mon algo me renvoie toujours la meme valeur qui est apparemment la case sur laquelle le joueur se trouve actuellement, ce qui n'est bien sur pas celle recherchee …

PS : je sais bien qu'il doit y avoir beaucoup de truc a factoriser mais c'est un premier jet donc je reverrai ca au fur et a mesure mais deja les fonctions findCheapestInOpenlist() et computeCostsChildren() me paraissent fortement similaire donc il doit y avoir un truc a faire.

Hello, petit up pour dire que j'en suis toujours bloque a cette partie. Je vais sans doute essayer de recommencer le code de l'algo de 0 car je pense qu'il y a pas mal de trucs a ameliorer.

Cependant si cela interesse quelqu'un de m'aider a debuguer celui la, je pense que le probleme vient de ce test qui retourne toujours true dans la fonction computeChildrenCosts :

1
closeList.Contains(node) == false

comme je l'ai dit, je ne suis pas un expert des lists donc toute aide est bonne a prendre. (Je me suis aussi lance en paralelle dans le javaquarium pour ameliorer mes competence en Java et plus generalement en POO)

Tiens regarde ca, c'est mon référenciel quand je bloque sur un aStar : AStar

Tu as surement une bonne base il doit juste y avoir un petit bémol quelque part. Je regarderai ca ce soir si j'ai le temps.

En attendant mon petit conseil c'est d'éplucher ton code à chaque tour de boucle. Mets un BreakPoint et vérifie tes valeurs. Reprend comme exemple le lien que je t'ai passé pour faire tes testes et vérifié si tu dérivé ou non et tu finiras par trouver.

Bonne chance.

+0 -0

Salut,

je vais jeter un oeil a ton lien il m'a l'air bien complet. Pour l'implémentation de mon algo je me suis inspiré de ces 2 liens : video youtube article

Pour ce qui est des breakpoints ça me parait être une bonne idée faudra que je vois comment on les met en place sous Monodevelop mais il me semble que j'avais déjà essayé sans succès mais bon ça doit pas être sorcier. Par contre cet IDE comment vraiment à me gaver avec sa complétion automatique qui te fait écrire de la merde a longueur de temps …

Bref je revois tout ça et je reviens aux news

Ok comme je l'avais dit je suis reparti de 0 pour l'algo de recherche. J'ai donc reecrit tout mon algo de Astar en utilisant ton lien pour m'aider et il semblerai que maintenant ca marche. Je ne sais pas ce que j'avais loupe dans le precedent car j'ai eu l'impression qu'il n'y avait pas de difference entre les 2 algos que j'ai ecrit mais apparemment si :)

Toujours est il que j'avais compris l'algo et que j'ai sans doute du merder dans son implementation la premiere fois. Voici donc le nouveau code que je trouve aussi plus propre :

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

public class AstarSearch {

  private List<NodeClass> openList;       //list of nodes to analyze
  private List<NodeClass> closeList;      //list of nodes already analyzed
  private Vector3 startingPosition;       //starting position of the algorithm
  private Vector3 arrivingPosition;       //position the algorithm try to reach
  private NodeClass nodeTemp;             //used to insert new node in lists
  private int lowestFvalue;               //use to store the lowest f value of the open list elements
  private int lowestFindex;               //use to store the index of the element with the lowest f value in the open list
  private Vector3[] movement = new [] {Vector3.forward, Vector3.back, Vector3.left, Vector3.right};

  //function called to initialize the algorithme
  public void init (Vector3 currPosition, Vector3 arrPosition)
  {
      //initialization of the variables
      openList = new List<NodeClass> ();
      closeList = new List<NodeClass>();
      startingPosition = currPosition;
      arrivingPosition = arrPosition;
      
      //gathering of the starting point informations
      nodeTemp = new NodeClass (startingPosition);
      nodeTemp.setH (System.Convert.ToInt32 (Mathf.Abs (arrivingPosition.x - nodeTemp.getNodePosition().x) + Mathf.Abs (arrivingPosition.z - nodeTemp.getNodePosition().z)));
      nodeTemp.setG (0);
      nodeTemp.setF (nodeTemp.getH () + nodeTemp.getG ());
      nodeTemp.setParent (new Vector3 (666, 666, 666));       //setting parent to a default position
      
      //make sure the openList and the closeList are empty at the beginning of the algorithm
      openList.Clear ();
      closeList.Clear();
      
      //add it to the openList
      openList.Add(nodeTemp);
      
      //launch of the algorithme
      Astar ();
  }

  void Astar()
  {
      //do the algorithm until we reach the arriving position or the open list is empty
      do
      {
          lowestFvalue = 1000;
          lowestFindex = 1000;
          //look for the lowest f value in the open list
          for (int i = 0; i < openList.Count; i++)
          {
              //if the current f value is lower than lowestFvalue, then put it into the variable
              if(openList[i].getF() < lowestFvalue)
              {
                  lowestFindex = i;
                  lowestFvalue = openList[i].getF();
              }
          }
          //add the element with the lowest f value of the open list in the close list
          closeList.Add (openList [lowestFindex]);
          Debug.Log ("arriving Position : " + arrivingPosition);
          Debug.Log("last element of close list : " + closeList.Last().getNodePosition());
          //then remove it from the open list
          openList.RemoveAt (lowestFindex);
          //if the element added in the close list is the arriving point, then stop the algorithm
          if (closeList.Last ().getNodePosition () == arrivingPosition)
          {
              Debug.Log("arriving position reached");
          }
          //else continue
          else
          {
              bool[] allowMovement =  new [] {true, true, true, true};
              RaycastHit hit;
              //watch every element of the table
              for (int i = 0; i < allowMovement.Length; i++)
              {
                  //Ray used to test if there is any collision on the left
                  Ray collisionRay = new Ray (closeList.Last ().getNodePosition (), movement [i]);
                  
                  //Check if there is collision between the ray and any element and check if the tag is "EnvElement", if yes then don't allow the movement
                  if (Physics.Raycast (collisionRay, out hit, 1f) && (hit.collider.tag == "EnvElement" || hit.collider.tag == "Player"))
                      allowMovement [i] = false;
              }
              //compute children
              for(int i = 0; i < allowMovement.Length; i++)
              {
                  //if the movement is allowed
                  if(allowMovement[i] == true)
                  {
                      //create a new node with all the child informations
                      NodeClass nodeTemp2 = new NodeClass(new Vector3 (closeList.Last().getNodePosition().x + movement[i].x, closeList.Last().getNodePosition().y + movement[i].y, closeList.Last().getNodePosition().z + movement[i].z));
                      nodeTemp2.setH(System.Convert.ToInt32 (Mathf.Abs (arrivingPosition.x - nodeTemp2.getNodePosition().x) + Mathf.Abs (arrivingPosition.z - nodeTemp2.getNodePosition().z)));
                      nodeTemp2.setParent(closeList.Last().getNodePosition());
                      nodeTemp2.setParentG(closeList.Last().getG());
                      nodeTemp2.setG(nodeTemp2.getParentG() + 1 );
                      nodeTemp2.setF(nodeTemp2.getG() + nodeTemp2.getH());
                      //and add it to the openlist
                      openList.Add(nodeTemp2);
                  }
              }
          }
      }while(closeList.Last().getNodePosition() != arrivingPosition || openList.Count <= 0);
  }
  
}

Et je viens d'ajouter mes sources dans mon repertoire github donc si vous etes interesses vous pouvez y acceder ici : repertoire github

Bon finalement je viens de me rendre compte avec la console que mon script avait un petit probleme : je rajoute plusieurs fois le meme node dans la close list. J'ai donc essaye de rajouter un test pour que au moment de chercher les enfants du dernier node ajouter a la close list, on regarde s'ils ne sont pas deja dans la close list mais je n'ai pas encore trouve le moyen de faire marcher ce test.

Sinon autre probleme, cet algo me retourne une liste de node qui eux memes contiennent entre autre leurs coordonnees ainsi que celles de leur parent. Le soucis c'est que ca ne me donne pas pour autant les objets (car l'algo entre autre a trouver le chemin entre la position du joueur et celle de la souris pour "illuminer" le chemin et au clic faire bouger le joueur le long de ce chemin). J'ai donc pense a faire des raycasts pour chaque node pour trouver la case du terrain qui lui correspond, deja je ne sais pas si c'est tres conseille de faire des raycasts a tout va comme ca et ensuite de toutes facons mon raycast me retourne tout le temps null :

1
ray = Camera.main.ScreenPointToRay (aStarResult[i].getNodePosition());

Voila ou j'en suis actuellement donc si vous avez des suggestions pour resoudre ces problemes je suis a l'ecoute.

Bon je crois avoir trouve la cause du fait que j'explore plusieurs fois le meme noeud :

 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
    //function conputing children of a node depending on the movements allowed from this node
    private void computeChildren(bool[] allowMovement)
    {
        bool check = true;
        for(int i = 0; i < allowMovement.Length; i++)
        {
            //if the movement is allowed
            if(allowMovement[i] == true)
            {
                //create a new node with all the child informations
                NodeClass nodeTemp2 = new NodeClass(new Vector3 (closeList.Last().getNodePosition().x + movement[i].x, closeList.Last().getNodePosition().y + movement[i].y, closeList.Last().getNodePosition().z + movement[i].z));
                nodeTemp2.setH(System.Convert.ToInt32 (Mathf.Abs (arrivingPosition.x - nodeTemp2.getNodePosition().x) + Mathf.Abs (arrivingPosition.z - nodeTemp2.getNodePosition().z)));
                nodeTemp2.setParent(closeList.Last().getNodePosition());
                nodeTemp2.setParentG(closeList.Last().getG());
                nodeTemp2.setG(nodeTemp2.getParentG() + 1 );
                nodeTemp2.setF(nodeTemp2.getG() + nodeTemp2.getH());
                check = true;
                for(int j = 0; j < closeList.Count; j++)
                {

                    if(closeList[j].getNodePosition() == nodeTemp2.getNodePosition())
                       check = false;
                    Debug.Log("<<<<<<<<<<<<<<<closeList element : " + closeList[j].getNodePosition() + "  " + nodeTemp2.getNodePosition() + "  " + check + j);
                }
                for(int k = 0; k < openList.Count; k++)
                {
                    if(openList[k].getNodePosition() == nodeTemp2.getNodePosition() && openList[k].getF() < nodeTemp2.getF())
                        check = false;
                    Debug.Log("<<<<<<<<<<<<<<<openList element : " + openList[k].getNodePosition() + openList[k].getF() +  "  " + nodeTemp2.getNodePosition() + nodeTemp2.getF() + "  " + check + k);
                }
                if(check == true)
                {
                    Debug.Log("-----------child and weight : " +  nodeTemp2.getNodePosition() + "  " + nodeTemp2.getF());
                    //and add it to the openlist
                    openList.Add(nodeTemp2);
                }
            }
        }
    }

Cette fonction est cense calculer les enfants du dernier noeud ajoute a la close list, verifier que l'enfant n'est pas dans la deja dans la close list ou dans l'open list avec un poids plus faible et si toutes ces conditions sont remplies alors elle ajoute l'enfant a l'open list.

Tout marche tres bien jusqu'au calcul des enfants du troisieme noeud ajoute a la close list, a ce moment ni l'iterateur j ni k ne demarrent a 0 mais a 2 …

logs

ce qui est bizarre c'est que ca ne fait ca que sur le 3e noeud ajoute a la close list, et seulement pour ses enfants 2 et 3 (on ne voit pas sur l'image mais pour le calcul de l'enfant suivant la 4eme direction les iterateurs repartent de 0).

Franchement j'avoue que je seche car c'est la premiere fois qu'un probleme pareil m'arrive … Si vous voyez des incoherences dans cette fonction … merci de me le dire :) en attendant je vais peut etre passer un peu a la modelisation 3D des personnages histoire de changer

Apres verification, c'etait juste parce que l'option collapse de la console etait activee …

Par contre, le fait de faire ces tests dans ces boucles for imbriquees fait totalement lagger le highlighting de la case survolee … (j'ai teste en virant les tests donc les boucles for et ca ne lag pas du tout) Du coup je suis preneur de conseils m'aidant a diminuer la complexite de cette fonction car si ca commence deja a lagger avec le peu de fonctionnalites que j'ai implemente je suis mal barre …

Voici le nouveau code de la fonction :

 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
  //function conputing children of a node depending on the movements allowed from this node
  private void computeChildren(bool[] allowMovement)
  {
      bool check = true;
      for(int i = 0; i < allowMovement.Length; i++)
      {
          //if the movement is allowed
          if(allowMovement[i] == true)
          {
              //create a new node with all the child informations
              NodeClass nodeTemp2 = new NodeClass(new Vector3 (closeList.Last().getNodePosition().x + movement[i].x, closeList.Last().getNodePosition().y + movement[i].y, closeList.Last().getNodePosition().z + movement[i].z));
              nodeTemp2.setH(System.Convert.ToInt32 (Mathf.Abs (arrivingPosition.x - nodeTemp2.getNodePosition().x) + Mathf.Abs (arrivingPosition.z - nodeTemp2.getNodePosition().z)));
              nodeTemp2.setParent(closeList.Last().getNodePosition());
              nodeTemp2.setParentG(closeList.Last().getG());
              nodeTemp2.setG(nodeTemp2.getParentG() + 1 );
              nodeTemp2.setF(nodeTemp2.getG() + nodeTemp2.getH());
              check = true;
              for(int j = 0; j < closeList.Count; j++)
              {

                  if(closeList[j].getNodePosition() == nodeTemp2.getNodePosition())
                  {
                     check = false;
                      break;
                  }
                  Debug.Log("<<<<<<<<<<<<<<<closeList element : " + closeList[j].getNodePosition() + "  " + nodeTemp2.getNodePosition() + "  " + check + j);
              }
              if(check == true)
              {
                  for(int k = 0; k < openList.Count; k++)
                  {
                      if(openList[k].getNodePosition() == nodeTemp2.getNodePosition() && openList[k].getF() <= nodeTemp2.getF())
                      {
                          check = false;
                          break;
                      }
                      Debug.Log("<<<<<<<<<<<<<<<openList element : " + openList[k].getNodePosition() + openList[k].getF() +  "  " + nodeTemp2.getNodePosition() + nodeTemp2.getF() + "  " + check + k);
                  }
              }
              if(check == true)
              {
                  Debug.Log("-----------child and weight : " +  nodeTemp2.getNodePosition() + "  " + nodeTemp2.getF());
                  //and add it to the openlist
                  openList.Add(nodeTemp2);
              }
          }
      }
  }

EDIT : Apres building du projet en executable ca lag beaucoup moins ce qui est comprehensible mais je reste persuade que la fonction est perfectible pour ameliorer la vitesse d'execution.

Salut, A mon avis ce n'est pas l'AStar en tant que tel qui fait larguer mais plutôt le nombre de fois ou tu l'appel. Je ne sais pas quand tu l'appels mais il est sensé tourner a chaque changement de case uniquement et pas tant qu'un case est highlight.

Si c'est déjà le cas et que ça lague uniquement quand on passe d'une case a l'autre. Dans ce cas oui essaye de voir si l'astar n'est pas opti. Ensuite c'est possible que même opti tu puisse laguer a cause du PC ou de la scène qui est déjà charger pour x raison que ce soit. Dans ce cas essaye de threader. Du preservera la fluidité pendant que ton calculée sera fait en tache de fond.

Bon courage.

+0 -0

Ok merci beaucoup Arius. Je suis desole pour le derangement, a la base j'avais poste dans la section multimedia car je pensais juste demander un conseil et au final ca s'est fini par devenir un vrai fil d'actualite du projet :)

Pour ce qui est des alertes, si tu parles du bouton signaler je pensais que c'etait plus pour signaler les abus, les messages irrespectueux etc …

Sinon pour ce qui est de l'avancee : je viens de regler plusieurs details. Tout d'abords, le code est mieux factorise, l'algo du aStar est appele seulement lorsque necessaire (c-a-d lorsque la case survolee change). Il me reste maintenant a trouver le probleme du surlignement du chemin trouve. Pour l'instant il se surligne mais ma fonction pour remettre la couleurs lorsque le chemin change n'est pas fonctionnelle, elle laisse toujours une ou deux cases dans la couleur que j'utilise pour surligner. Je vais update le github avec le nouveau code quand j'aurai fini de commenter tout ca et que j'aurai un peu supprimer tous les logs que j'utilisais pour debug.

EDIT : probleme de reset du highlight regle. C'etait du a une erreur d'index dans la fonction qui devait s'en charger. De plus je viens de finir de supprimer tous les logs et wow ! Le Astar s'execute beaucoup plus fluidement, plus de probleme de ralentissement. Faut dire que j'avais un peu abuse sur les Debug.Log :D
Du coup le code est update sur le github (voir dans ma signature)

EDIT 2 : Je viens de remarquer en fait que pour definir la distance de deplacement j'utilisais la distance de Manhattan et ca ne va pas. Pour l'algo de Astar c'est approprie mais dans mon jeu, le joueur n'aura qu'un certain nombre de points de mouvement pas tour. La pour le moment je lance l'algo seulement si le raycast touche le sol a moins de 4 cases du joueur (4 pts de mouvement pour le moment). Le soucis c'est que lorsqu'un obstacle se trouve sur le chemin, l'algo va faire un detour pour arriver a la destination mais au final le joueur se deplacera de plus de 4 cases. Le probleme vient du fait que par la distance de manhattan, la case se trouve tout de meme etre a 4 cases ou moins du joueur. Du coup il faut que je reflechisse a un test plus approprie, tout en pouvant le faire avant de lancer l'algo parce que si je suis oblige de faire tourner l'algo pour ensuite verifier si le joueur a le droit de se deplacer c'est pas terrible

En fait je pense que ce que je vais faire c'est que je vais lancer l'algo si la souris est a distance de 4 cases en distance manhattan par rapport a la position du joueur et je vais ajouter un test a la fin pour voir si le chemin trouve est plus long que 4 ou pas. Ca fera tourner l'algo pour rien certaines fois mais c'est plutot pas trop mal comme solution de toutes facons et je vois pas comment faire autrement. Je modifie le code dans les jours qui viennent.

PS : desole pour le double post mais je sais pas ce qu'il se passe a chaque fois que je veux editer mon message, la page charge a l'infini avant de m'afficher une erreur de chargement … Je ne sais pas si ca vient de ma connexion ou du site

EDIT : Ajout du test sur la longueur du chemin trouve par le Astar termine. Tout marche nikel. To Do List :
- deplacement du joueur selon le chemin (pour l'instant il se tp a l'arrive directement)
- amelioration du fonctionnement des tours (pour l'instant le tour se fini apres le deplacement du joueur, je voudrais laisser la possibilite au joueur de faire des actions avant et aussi realiser ses deplacements en plusieurs etapes donc ajout d'un bouton fin de tour)
- ajout des mecanismes de combat
- ajout des zones de vision (ne pas permettre a un joueur d'en taper un autre si un obstacle se trouve entre eux, meme s'il attaque a distance. A terme, les sorts auront des portes, des zones de visions et des couts differents)

Bonjour, ajout du deplacement selon le chemin du aStar. J'avoue avoir bien galere pour trouver comment faire. L'utilisation des coroutines n'etant pas mon fort. Mais grace a l'aide que NDrew et Alesk m'ont apporte sur le forum de unity3d-france, j'ai reussi a mettre en place la coroutine.
D'ailleurs je tiens a remercier tout particulierement Alesk qui m'a non seulement aide mais aussi donne un code fonctionnel et je n'en attendais pas tant :p . Du coup ma coroutine est tres similaire a ce qu'il m'a fourni meme si j'ai du y modifier quelques trucs pour que ca colle a mon cas.

J'ai aussi rajoute 2-3 lignes pour gerer l'orientation du personnage durant le travel time histoire qu'il soit oriente dans la bonne direction et qu'il ne marche pas a reculons ou en crabe. L'animation de marche est lancee lors du debut de la coroutine et est arretee a la fin de celle ci avec un retour a l'animation de idle. Voici donc le code de la coroutine :

  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
  IEnumerator applyMove(List<NodeClass> path)
  {
      //notify the player is moving
      isMoving = true;
      //get the child of the Gameobject, it is the model containing the animations
      GameObject thisChild = new GameObject();
      foreach(Transform child in transform)
      {
          if(child.name == "samuzai")
          {
              thisChild = child.gameObject;
          }
      }
      //play the walk animation
      thisChild.animation.Play("Walk");
      
      //travelled distance from starting point
      float travelDistance = 0;
      
      //starting point
      Vector3 startPosition = transform.position;
      
      //loop on every node of the path
      for(int i = path.Count-2 , count = path.Count, lastIndex = 0 ; i >= 0; i--)
      {
          
          //distance between starting point and arriving point (current node, next node)
          float distance = Vector3.Distance(startPosition, path[i].getNodePosition());
          
          //oriantation vector between those 2 points
          Vector3 direction = (path[i].getNodePosition() - startPosition).normalized;

          //set the orientation of the player according to the direction he is moving to
          Quaternion lookAt = Quaternion.LookRotation(path[i].getNodePosition() - transform.position);
          transform.rotation = Quaternion.Lerp(transform.rotation, lookAt, 1f);
          
          //loop until we did not pass the position of the next node
          while(travelDistance < distance)
          {
              
              //we go forward according to the moving speed and the time past
              travelDistance += (speed * Time.deltaTime);
              
              //if we passed or reached the arriving node position
              if(travelDistance >= distance)
              {
                  
                  //if we have still nodes left in the path list 
                  if(i > lastIndex)
                  {
                      //we go further in the path 
                      //between the 2 next nodes, substractign the distance already travelled beyond the current arriving node
                      float distanceNext = Vector3.Distance(path[i-1].getNodePosition() , path[i].getNodePosition());
                      float ratio = (travelDistance - distance) / distanceNext;
                      
                      //if the ration is greater than 1, then the distance travelled is also greater than the distance between the 2 next nodes (so we move too fast)
                      //this loop will skip all the nodes that we are supposed to have already gone through by moving very fast (not really usefull in my case)
                      while(ratio > 1)
                      {
                          i--;
                          if(i == lastIndex)
                          {
                              //we reached the last node
                              transform.position = path[i].getNodePosition();
                              //go out of the loop
                              break;
                          }
                          else
                          {
                              travelDistance -= distance;
                              distance = distanceNext;
                              distanceNext = Vector3.Distance(path[i-1].getNodePosition() , path[i].getNodePosition());
                              ratio = (travelDistance - distance) / distanceNext;
                          }
                      }
                      
                      if(i == lastIndex)
                      {
                          //we reached the last node of the path in the previous while loop
                          break;
                      }
                      else
                      {
                          transform.position = Vector3.Lerp(path[i].getNodePosition() , path[i-1].getNodePosition(), ratio);
                      }
                  }else{
                      //we reached the last node of the path
                      transform.position = path[i].getNodePosition();
                      break;
                  }
              }
              else
              {
                  //else we go forward in the direction of the arriving point
                  transform.position += direction * (speed * Time.deltaTime);
              }
              
              yield return null;
          }
          
          //we substract the distance that we had to travel between the 2 previous nodes on retire la distance qu'il y avait à parcourir entre les deux nodes précédents
          travelDistance -= distance;
          
          //update of the starting point for the next iteration
          startPosition = path[i].getNodePosition();
      }
      //stop the walk animation and play the idle one
      thisChild.animation.Stop("Walk");
      thisChild.animation.Play("idle");
      //notify the player is not moving anymore
      isMoving = false;
  }

To Do List :
- deplacement du joueur selon le chemin (pour l'instant il se tp a l'arrive directement)
- amelioration du fonctionnement des tours (pour l'instant le tour se fini apres le deplacement du joueur, je voudrais laisser la possibilite au joueur de faire des actions avant et aussi realiser ses deplacements en plusieurs etapes donc ajout d'un bouton fin de tour)
- ajout des mecanismes de combat
- ajout des zones de vision (ne pas permettre a un joueur d'en taper un autre si un obstacle se trouve entre eux, meme s'il attaque a distance. A terme, les sorts auront des portes, des zones de visions et des couts differents)

Petit up pour dire que j'ai mis en place le systeme de tours comme je le souhaitais. Maintenant le joueur doit appuyer sur la touche M pour passer le tour (ca se fera avec un bouton a terme mais pour l'instant comme j'ai pas unity 4.6 sur toutes mes machines j'ai pas envie de m'embeter avec des potentiels conflits).
Un systeme de comptage de points de mouvements utilises a donc aussi ete mis en place afin que les joueur puisse pas exemple se deplacer d'une case, faire une action, puis utiliser le reste de ses points de mouvements (l'utilisation complete de ceux ci n'est pas obligatoire).
Du coup la prochaine etape est donc de coder les principes d'un systeme de combat basique (attaque au corps a corps pour commencer) qui sera etoffe au fur et a mesure apres que j'ai modelise d'autres modeles (j'ai poste une video sur mon compte youtube, je mets le lien des quelle a finit d'upload).
EDIT : lien vers la video youtube

Et bien ca avance mine de rien, continu comme ca !

Petite remarque, avant de commencer la partie combat, tu pourrais peut être étoffer encore un petit peu le déplacement. En mettant en surbrillance toutes les cases disponibles par exemple. On aurait une meilleur vision de ce qu'il est possible ou non de faire. Tu pourras même réutiliser cette technique pour afficher les cases d'attaque à distance.

Après fait comme tu le sens ce n'est qu'une proposition. ;)

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

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