Создание сетки в Unity для A*

Начал попытки сделать свою MOBA и первое что пришло в голову это передвижение с поиском пути. Конечно все это можно было реализовать через AI NavMesh, я заинтересовался как это работает. Захотел попробовать реализовать собственный скрипт поиска пути. Знаю, зачем изобрать велосипед когда он уже придумал. Но все же хотелось бы узнать для развития которое остановилось. Как мне стоит реализовать скрипт для создания сетки?


Ответы (1 шт):

Автор решения: Павел Чагарный

Я решил так (когда-то давно))):

public class Pointer : MonoBehaviour {

public bool isActive=true;
public bool isFound=false;
public int step=0;
static float dist = 5f;
static float tdist = dist * 1.2f;
public static int limit = 80;
public static bool permission = true;
public static int id = 0;
public Transform tar;
public GameObject parent=null;
static List<GameObject> pointers = new List<GameObject> ();
public static List<GameObject> path = new List<GameObject> ();
public static bool isPathNotFound = false;
// Use this for initialization

void Start () {
    if (!permission)
        return;
    if (isActive) {
        createPointers (transform.forward);
        createPointers (transform.right);
        createPointers (-transform.forward);
        createPointers (-transform.right);
    }
    isActive = false;
    //limit--;
    if (step>limit) {
        permission = false;
    }
    if (!isPathExist ()) {
        Debug.Log ("Path isn\'t exists!");
        permission = false;
        isPathNotFound = true;
    }
}

// Update is called once per frame
void Update () {
    
}
    
public void createPointers(Vector3 dir){
    if (isFound)
        return;
    Vector3 pos = transform.position+dir*dist;
    if (isCanCreate (dir)) {
        GameObject p = GameObject.CreatePrimitive (PrimitiveType.Capsule);
        p.transform.position = pos;
        //test it ***
        if (!setHeight (p)) {
            Destroy (p);
            return;
        }
        //***
        p.AddComponent<Pointer> ();
        p.GetComponent<Pointer> ().tar = tar;
        p.GetComponent<Pointer> ().step = step + 1;
        id++;
        p.name = "Pointer_" + id;
        p.GetComponent<Pointer> ().parent = gameObject;
        pointers.Add (p);
        if (p.GetComponent<Pointer> ().isTargetFound ()) {
            isActive = false;
            isFound = true;
            permission = false;
        }
    }
}
//test it
bool setHeight(GameObject p){
    Vector3 pos = p.transform.position;
    p.transform.position = new Vector3 (pos.x, Mathf.Infinity, pos.z);
    Ray ray = new Ray (p.transform.position, -Vector3.up);
    RaycastHit hit;
    if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
        if (hit.collider.tag == "ground") {
            p.transform.position = new Vector3 (pos.x, hit.point.y+2, pos.z);
            return true;
        }
    }
    return false;
}
//***
bool isCanCreate(Vector3 dir){
    Ray ray = new Ray (transform.position, dir);
    RaycastHit hit;
    if (!Physics.Raycast (ray, out hit, tdist)) {
        ray = new Ray (transform.position+dir*dist, -Vector3.up);
        if (!Physics.Raycast (ray, out hit, Mathf.Infinity)) {
            //Debug.Log ("pointer_" + id + " is out of map!");
            return false;
        }
        return true;
    }
    else
        return false;
}
bool isTargetFound(){
    Ray ray = new Ray (transform.position, tar.position-transform.position);
    RaycastHit hit;
    if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
        if (hit.collider.gameObject.name == tar.name) {
            Debug.Log ("target is found!\nPointer id: " + id);
            isFound = true;
            Debug.Log ("pointers count: " + pointers.Count);
            getPath (gameObject);
            return true;
        }
        else
            return false;
    }
    return false;
}
bool isPathExist(){
    if (pointers.Count == 0) {
        return false;
    }
    for (int i = 0; i < pointers.Count; i++) {
        if (pointers [i].GetComponent<Pointer> ().isActive) {
            return true;
        }
    }
    return false;
}
void getPath(GameObject gf){
    path.Add (gf);
    if (pointers.Count == 0) {
        Debug.Log ("pointers count==0!!!");
        path = new List<GameObject> ();
        return;
    }
    for (int i = 0; i < pointers.Count; i++) {
        Pointer ps = gf.GetComponent<Pointer> ();
        if (ps.parent == null) {
            Debug.Log ("(in break) path count: " + path.Count);
            break;
        }
        path.Add (ps.parent);
        gf = ps.parent;
    }
    path.RemoveAt(path.Count - 1);
    for (int i = 0; i < pointers.Count; i++) {
        GameObject.Destroy (pointers [i]);
    }
    for (int i = 0; i < path.Count; i++) {
        GameObject.Instantiate (path [i]);
    }
    Debug.Log ("path count: " + path[0]);
}

}

Вешать на того кто ищет. "Таргет" задается в инспекторе (или программно, тогда поправить код нужно). У меня работает с террайном и мешами, но скрипт, если честно уже не помню как работает. Но проэкт в целом работает )).

→ Ссылка