算法简介:
A*搜寻算法俗称A星算法。A*算法是比较流行的启发式搜索算法之一,被广泛应用于路径优化领域[。它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价该节点处于最短路线上的可能性的量度。[1] - 百度百科
通俗点说,就是在起点与目标点之中找出一条可通行的最短路线。常见于各类RPG游戏中的自动寻路功能:点击某个任务,人物会自动移动过去;点击地图上某个点,人物也会照着显示出来(或者隐藏了)的路线前进。玩过LoL,红色警戒等类似游戏的小伙伴都知道,右击小地图的某一处,小地图会出现一条从当前位置到所点击位置的红色路线,然后英雄就会随着这条路线一直走到目标点。这种功能,就是A*算法的在游戏中的常见应用之处。
场景布置:
1 布置地面:场景中新建一个Plane(地面)重置一下Transform,然后将Scale拉伸至20倍(此时地面的大小是200x200),地面是不带y坐标的,即只有xz平面,此时平面上左下角坐标点是(-100,-100),右上角是(100,100)这个很重要,后面的判断坐标点是否越界(超出地面范围)就是依据这个地面的大小和坐标
2 布置障碍物:新建一个空物体Bars,在Bars下创建一个cube,将cube随便拉伸做成一堵墙,然后复制,摆放到场景上各个位置。
3 创建玩家:场景中新建一个Capsule(为了好控制,就选用胶囊体了),取名为Player,为它挂上Character Controller角色控制器。
4 路线:新建一个Sphere球,涂成红色,改名叫Way,卸载掉Collider(一定要卸载),做成预制体,用来表示计算出来的路线上的每一点。新建一个空物体Ways,用来存储路线
5 层级设置:为了代码中好检测,为地面Plane设立一个单独的层Plane,层级号位9.所有障碍物层级为Bars,层级号为8
脚本编辑:
脚本没写的太过复杂,就编写了两个脚本:
PlayerCtrl.cs 用来控制玩家移动
AStarRun.cs 用A*算法来计算起点到目标点的最佳路径并返回
将这两个脚本都挂载在玩家上(Player)
PlayerCtrl.cs 用来控制玩家移动
using UnityEngine;using System.Collections;//玩家控制器public class PlayerCtrl : MonoBehaviour {
public GameObject wayLook;//寻路线的红点
public float moveSpeed = 10f;//角色前进速度
private CharacterController cc;//角色控制器
private Transform waysParent;//寻路线的放置位置
private Ray ray;//射线检测鼠标点击点
private RaycastHit hit;
private bool IsMove = false;//是否正在寻路过程
void Start ()
{
cc = GetComponent<CharacterController>();
waysParent = GameObject.Find("Ways").transform;
}
void Update ()
{
//鼠标单击移动
if(Input.GetMouseButtonDown(0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);//获取主相机到鼠标点击点的射线
//检测射线是否碰撞到地面:地面的层级是9
if(Physics.Raycast(ray,out hit,1 << 9))
{
//往目标点移动过去
//return;
Vector3 starPoint = new Vector3(transform.position.x,0,transform.position.z);//寻路的起点
Vector3 targetPoint = new Vector3(hit.point.x,0,hit.point.z);//寻路的终点
if(!IsMove)
StartCoroutine(AutoMove(starPoint,targetPoint));//开启自动寻路
}
}
}
/// <summary>
/// 自动寻路协程
/// </summary>
/// <returns>The move.</returns>
/// <param name="starPoint">起点.</param>
/// <param name="targetPoint">目标点.</param> IEnumerator AutoMove(Vector3 starPoint,Vector3 targetPoint)
{
IsMove = true;
yield return new WaitForFixedUpdate();
//运用A星算法计算出到起点到目标点的最佳路径
Vector3[] ways = GetComponent<AStarRun>().AStarFindWay(starPoint,targetPoint);
if(ways.Length ==