Alors en fait pour les struc : Par exemple Vector3 est un struc, avec x, y et z comme éléments. Un struc c'est comme une variable, qui aurait plusieurs élément. Par exemple :
Code : Tout sélectionner
public struct CASE {
public int x;
public int y;
public bool obstacle;
public GameObject G;
public CASE(int x, int y,bool obstacle,GameObject G) {
this.x = x;
this.y = y;
this.obstacle = obstacle;
this.G = G;
}
CASE perso; // créé une variable CASE
CASE[] persoMultiple // defini un aarray de la struct CASE
}
Je peux donc accéder comme pour un vector3 :
perso.x => l'élément int x de la variable perso, étant une struct CASE.. etc
persoMultiple
.x => l'élément int x de la CASE persoMultiple a l'index i.. etc
tu auras compris, dans une struct tu peut lui assigner autant d'élément que tu veux, de n'importe quel type (float, int, component,GameObjec... cetc)
En me servant de ce principe, me suis permis d'en modifier ton code pour s'en servir, si tu veux jeter un coup d'oeil :
chaque cellule devra se voir attribuer un collider et ce script :
Code : Tout sélectionner
using UnityEngine;
public class Tile : MonoBehaviour {
public int Index; // sera assigné au lancement du niveau. il correpondra a son index dans l'array cellule( array de struct)
// !! la cellule doit comporter un collider couvrant sa surface!!
void OnMouseEnter(){
// si on survole avec la souris la cellule
// on assign
chemin.ACTIVE = Index;
}
void OnMouseDown(){
// si on clique sur la cellule, on assignson Index comme start, et lance la recherche de chemin
// chemin
chemin.end = Index;
chemin.RechercheChemin();
}
}
et le script général :
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class chemin : MonoBehaviour {
// definition d'une struc pour garder les donnée dans le script
// pour n'acceder qu'une seule fois aux GameObject cellule.
public struct CEL {
public Vector3 position;
public bool visite;
public List<int> voisin;
public bool carrefour;
public CEL(Vector3 position , bool visite, List<int> voisin , bool carrefour) {
this.position = position;
this.visite = visite;
this.voisin = voisin;
this.carrefour = carrefour;
}
}
public static int ACTIVE; // cellule survolée par la souris
public static GameObject Mimi; // ton personnage, devra avoir le tag "mimi"
public static CEL[] cellules; // un array de la struct CEL defini plus haut
public static List<List<int>> Paths; // liste de tout lein possile
public static List<int> Path; // le path qu'on est en train de calculer puis le path court retenu.
public static int end; // index de cellules ou se trouve l'arrivé.
public static int start; // index de cellules ou se trouve mimi.
public static int EnCours; // l'index de la case ou en est la recherche de chemin.
// Use this for initialization
void Start () {
// recherche du perso
Mimi = GameObject.FindGameObjectWithTag("mimi");
ACTIVE = 0;
// lance l'initialisation de la struct
Initialisation();
Path = new List<int>();
}
void Update(){
// juste un debugage que me suis servit pour visualiser les chemin.
for ( int i = 0 ; i < cellules[ACTIVE].voisin.Count; i++){
Debug.DrawLine( cellules[ACTIVE].position, cellules[cellules[ACTIVE].voisin[i]].position, Color.red);
}
for ( int i = 0 ; i < Path.Count-1 ; i++){
Debug.DrawLine( cellules[Path[i]].position, cellules[Path[i+1]].position, Color.blue);
}
Debug.DrawRay(cellules[end].position, Vector3.up , Color.red);
Debug.DrawRay(cellules[start].position, Vector3.up , Color.green);
Debug.DrawRay(cellules[ACTIVE].position, Vector3.up*2 , Color.blue);
}
void Initialisation(){
GameObject[] CelluleGO = GameObject.FindGameObjectsWithTag("cellule") ;
cellules = new CEL[CelluleGO.Length];
for ( int i = 0 ; i < cellules.Length ; i ++){
cellules[i].position = CelluleGO[i].transform.position;
cellules[i].visite = false;
cellules[i].voisin = new List<int>();
cellules[i].carrefour = false;
CelluleGO[i].GetComponent<Tile>().Index = i; // on assigne au GameObject cellule l'index dans lequel il se trouve
}
RechercheVoisin();
}
void RechercheVoisin(){
for ( int i = 0 ; i < cellules.Length-1; i++){
for ( int j = i+1; j < cellules.Length; j++){
float distance = (cellules[i].position - cellules[j].position).magnitude;
if( Mathf.Approximately(distance, 1f)){
if( !cellules[i].voisin.Contains(j)){
cellules[i].voisin.Add(j);
cellules[j].voisin.Add(i);
}
}
}
}
// apres avoir trouvé tout les voisins
// on assigne le bool carrefour en fonction du nombre de voisins.
for ( int i = 0 ; i < cellules.Length-1; i++){
if( cellules[i].voisin.Count>2){
cellules[i].carrefour = true;
}
}
}
public static void OuEstMimi(){
// on determine sur quelle case se trouve mimi
// pour le point de depart des path
for ( int i = 0 ; i < cellules.Length ; i++){
float distance = (cellules[i].position - Mimi.transform.position).magnitude;
if( distance< 1.0f){
start = i;
return;
}
}
}
public static void RechercheChemin(){
// on assign false a toute les cellule ( a sa struct qui lui correspond)
for ( int i = 0 ; i < cellules.Length ; i++){
cellules[i].visite = false;
}
// remise a zero des paths possible. On efface tout on recommence
Paths = new List<List<int>>();
Path = new List<int>();
retour:
OuEstMimi(); // recherche de la case ou se trouve mimi
EnCours = start;
Path.Add(EnCours); // ajout de la case
cellules[EnCours].visite = true; // la cellule ou se trouve mimi est marquée visitée.
RechercheCheminPossible();
if (Path.Count > 0 && Path.Count < 5){
return;
}
if (Path.Count > 1){
Paths.Add(Path);
}
EnCours = start;
if (RechercheCarrefour(EnCours)){
goto retour;
}
if (Paths.Count > 0){
RechercheLePlusCourt();
}
}
public static void RechercheCheminPossible(){
retour:
//s'il y a une cellule voisine à de la cellule en cours
if (RechercheCarrefour(EnCours)){
//on l'ajoute au chemin
Path.Add(EnCours); // ajout de l'index de la cellule au chemin
cellules[EnCours].visite = true;
//si on est arrivé
if (EnCours == end)
{
//on demarque visité de la dernière cellule en cas de recherche supplémentaire et on sort
cellules[EnCours].visite = false;
return;
}
//sinon on continue
goto retour;
}
//il n'y a pas de cellule accessible autour de la cellule en cours
for (int i = Path.Count - 1; i > -1; i--){
//on remonte le chemin à la recherche d'un carrefour
if (!RechercheCarrefour(Path[i])){
Path.Remove(Path[i]);
}
else{
//on reprend à partir du carrefour
EnCours = Path[i];
goto retour;
}
}
return;
}
static bool RechercheCarrefour(int index) {
foreach (int item in cellules[index].voisin) {
//if (item != null && item.gameObject.activeSelf)
if (cellules[item].visite == false){
EnCours = item;
return true;
}
}
return false;
}
public static void RechercheLePlusCourt(){
Path = Paths[0]; // on prend le premier Path de Paths
foreach (var item in Paths){
if (item.Count < Path.Count)
Path = item;
}
}
}
Pour la partie pathFinding, j'ai rien touché, ça marche plutôt bien!
Juste adapter pour le struct.
juste ajouté une fonction OuEstMimi(), pour savoir sur quelle case ( index) elle se trouve quand un cherche un chemin. Je savais pas comment tu gérais ça.
Et un petit debug dans la void Update() pour voir si tout est bien en place