using UnityEngine;
using System.Collections;
///引用cube
public class ReferenceCube : MonoBehaviour {
//定义每个格子所对应的坐标
private int x;
private int y;
//构造坐标方法
public void SetPos(int currentX, int currentY)
{
x = currentX;
y = currentY;
}
/// <summary>
/// 触发检测,判断每个格子所对应的类型:start、end、obstacle、normal
/// </summary>
/// <param name="other"></param>
void OnTriggerEnter(Collider other)
{
//若格子触发的是start对象,则为start型
if (other.tag == CubeTags.startTag)
{
AStar.instance.grids[x, y].type = GridType.start;
//格子的彩色球颜色与start对象一致
gameObject.GetComponent<MeshRenderer>().material.color = other.GetComponent<MeshRenderer>().material.color;
//初始坐标为start对象所在的坐标
AStar.instance.startX = x;
AStar.instance.startY = y;
//Debug.Log(AStar.instance.grids[x, y].x + " &" + AStar.instance.grids[x, y].y);
}
//若格子触发的是end对象,则为end型
else if (other.tag == CubeTags.endTag)
{
AStar.instance.grids[x, y].type = GridType.end;
//颜色一致
gameObject.GetComponent<MeshRenderer>().material.color = other.GetComponent<MeshRenderer>().material.color;
//结束点坐标与end对象坐标一致
AStar.instance.endX = x;
AStar.instance.endY = y;
//Debug.Log("---------------------------");
//Debug.Log(AStar.instance.grids[x, y].x + " &" + AStar.instance.grids[x, y].y);
}
//若格子触发的是obstacle对象,则为obstacle型
else if (other.tag == CubeTags.obstacle)
{
AStar.instance.grids[x, y].type = GridType.obstacle;
//颜色一致
gameObject.GetComponent<MeshRenderer>().material.color = other.GetComponent<MeshRenderer>().material.color;
}
else
//若不是以上的三种类型,则为normal型
{
AStar.instance.grids[x, y].type = GridType.normal;
}
}
}
主逻辑
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 格子类型的枚举
/// </summary>
public enum GridType
{
start,
end,
obstacle,
normal
}
/// <summary>
/// AStar类,挂在AStar的空物体上
/// </summary>
public class AStar : MonoBehaviour {
//单例类
public static AStar instance;
//引入cube对象
private GameObject referenceCube;
//偏移量
public Vector3 offset;
//格子的横竖排数量
private int row = 20;
private int column = 20;
//可选格子列表:用于储存每个被选格子周围的上下左右,左上左下右下右上的格子
private ArrayList canSelectList;
//被选格子列表:用于储存每次比较之后F值最小的格子
private ArrayList selectedList;
//定义一个格子数组(根据每个格子的坐标)
public Grid[,] grids;
//定义一个游戏对象数组(根据游戏对象的坐标)
private GameObject[,] objs;
//开始位置的坐标
public int startX;
public int startY;
//结束位置的坐标
public int endX;
public int endY;
//用栈来储存selectedList中的值(每次比较之后的F值最小格子)
private Stack result;
/// <summary>
/// 初始化
/// </summary>
void Awake()
{
referenceCube = Resources.Load<GameObject>("ReferenceCube");
canSelectList = new ArrayList();
selectedList = new ArrayList();
grids = new Grid[20,20];
objs = new GameObject[20, 20];
result = new Stack();
}
/// <summary>
/// 实例化20*20格子
/// </summary>
void Start()
{
instance = this;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
grids[i, j] = new Grid(i, j);
GameObject currentCube = Instantiate(referenceCube, new Vector3(i * 0.5f, 0, j * 0.5f) + offset, Quaternion.identity) as GameObject;
currentCube.GetComponent<ReferenceCube>().SetPos(i, j);
objs[i, j] = currentCube;
}
}
//开启协程
StartCoroutine(CountAStar());
}
/// <summary>
/// 计算AStar寻路中每个格子的F值,然后做比较,储存在相应的ArrayList中
/// </summary>
/// <returns></returns>
IEnumerator CountAStar()
{
yield return new WaitForSeconds(0.3f);
//将开始点的格子加入到可选列表中
canSelectList.Add(grids[startX, startY]);
//作为可选列表的第一个元素
Grid currentGrid = canSelectList[0] as Grid;
//若当前的格子不是终点,并且可选格子中有对象,执行下面,否则跳出
while (currentGrid.type != GridType.end && canSelectList.Count > 0)
{
//则定义currentGrid为可选格子列表中的第一个元素
currentGrid = canSelectList[0] as Grid;
//若
if (currentGrid.type == GridType.end)
{
Debug.Log("find the path");
GenerateResult(currentGrid);
}
else if (canSelectList.Count == 0)
{
Debug.Log("no grid");
}
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i != 0 || j != 0)
{
int x = currentGrid.x + i;
int y = currentGrid.y + j;
if(x > 0 && y > 0 && x < row && y < column && !selectedList.Contains(grids[x, y]) &&
grids[x, y].type != GridType.obstacle)
{
//计算g值
int g = currentGrid.G + (int)(Mathf.Sqrt(i * i + j * j) * 10);
//更新g值
if (grids[x,y].G == 0 || g <grids[x,y].G)
{
grids[x, y].G = g;
grids[x, y].parrent = currentGrid;
}
grids[x, y].H = (int)(Mathf.Abs(endX - x) + Mathf.Abs(endY - y)) * 10;
grids[x, y].F = grids[x, y].G + grids[x, y].F;
//若不包括在可选arraylis中,加入
if (!canSelectList.Contains(grids[x, y]))
{
canSelectList.Add(grids[x, y]);
}
}
}
}
}
canSelectList.Sort();
selectedList.Add(currentGrid);
canSelectList.Remove(currentGrid);
}
}
void GenerateResult(Grid currentGrid)
{
if (currentGrid.parrent != null)
{
result.Push(currentGrid);
Debug.Log(currentGrid.x +"/" + currentGrid.y);
iTween.ColorTo(objs[currentGrid.x, currentGrid.y], Color.blue, 3f);
GenerateResult(currentGrid.parrent);
}
}
}
tag值
using UnityEngine;
using System.Collections;
/// <summary>
/// 场景中的对象所对应的tag值脚本
/// </summary>
public class CubeTags {
public static string startTag = "Start";
public static string endTag = "End";
public static string obstacle = "Obstacle";
}
格子类
using UnityEngine;
using System.Collections;
using System;
/// <summary>
/// 记录格子的类
/// </summary>
public class Grid:IComparable
{
//格子所对应的坐标
public int x;
public int y;
//F=G+H,曼哈顿函数所涉及的三个值,其中F=G+H
//G为该点到起始点的估量代价
//H为该点到终止点的估量代价
//F值即为曼哈顿值
public int F;
public int G;
public int H;
//格子的类型
public GridType type;
//格子所对应的父物体
public Grid parrent;
//格子的坐标函数
public Grid(int i, int j)
{
x = i;
y = j;
}
/// <summary>
/// 该类继承一个IComparable接口,可以在该类中自定义一个方法,用于做比较
/// 如下:比较grid对象的F值的大小,最后按照从小到大的顺序排序
/// </summary>
/// <param name="grid"></param>
/// <returns></returns>
public int CompareTo(object grid)
{
if (this.F > ((Grid)grid).F)
{
return 1;
}
else if (this.F == ((Grid)grid).F)
{
return 0;
}
else
{
return -1;
}
}
}