插件核心脚本:
1.astarpath.cs 用于寻路 Component->Pathfinding->Pathfinder添加”astarpath.cs”
2.seeker.cs 用于需要寻路的物体
3.SimpleSmoothModifier.cs 调控路径使其更加圆滑、简单
步骤1:创建一个新层(edit->project settings->tags and layers),命名为”Ground”,把plane设为”Ground”,创建一些cube作为障碍物,把这些cube设为新的层”Obstacles”
步骤2:创建一个空物体命名为"A* 脚本”,选择物体,然后单击[Component] - [Pathfinding] - [Pathfinder]
步骤3 :创建"控制对象"物体,选择[Component] - [Pathfinding] - [Seeker] ,载入插件脚本,用于寻路
Pathfinder脚本作用是在Unity3D地图上生成路径网格,为路径规划策略提供前提。
效果如图所示:
路径网格生成脚本Pathfinder中的参数:
Width和Depth : 网格长度和宽度设置,为Transform的X10,即Plane(10,0,10),则(Width,Depth)=(100,100)
Obstacle Layer Mask:如步骤1设置,用于避障
其它参数自行摸索。
平滑脚本Simple Smooth中的参数:
Max Segment Length : 路径点之间的距离
Iterations : 迭代次数,路径的平滑系数
Strength : 路径的强硬系数
“Astar AI”脚本作用是对插件规划出的路径Path点做处理,然后进行简单的控制:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
using System;
public class AstarAI : MonoBehaviour
{
//目标物体与目标位置
public GameObject targetObject;
private Vector3 targetPosition;
private Seeker seeker;
//存储路径
public Path path;
//角色移动速度
public float speed = 100.0f;
public float turnSpeed = 5f;
//判断玩家与航点的距离
public float nextWaypointDistance = 3;
//对当前的航点进行编号
private int currentWaypoint = 0;
// Start is called before the first frame update
public Transform obj_g;
void Start()
{
seeker = GetComponent<Seeker>();
//注册回调函数,在Astar Path完成后调用此函数
seeker.pathCallback += OnPathComplete;
}
// Update is called once per frame
void FixedUpdate()
{
targetPosition = targetObject.transform.position;
//开始寻路
if (Input.GetKey(KeyCode.K)) { seeker.StartPath(transform.position, targetPosition); }
if (path == null)
{
return;
}
if (Vector3.Distance(transform.position, path.vectorPath[currentWaypoint + 1])<3)
{
currentWaypoint++;
}
Vector3 dir = (path.vectorPath[currentWaypoint + 1] - transform.position);//.normalized;
dir *= speed * Time.fixedDeltaTime;
//玩家转向
transform.Translate(Vector3.forward * Time.fixedDeltaTime * speed);
Quaternion targetRotation = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * turnSpeed);
Debug.Log($"目标朝向{targetRotation.eulerAngles.y},目标X{path.vectorPath[currentWaypoint].x}");
obj_g.transform.position = path.vectorPath[currentWaypoint+1];
}
/// <summary>
/// 当寻路结束后调用这个函数
/// </summary>
/// <param name="p"></param>
private void OnPathComplete(Path p)
{
//Debug.Log("发现这个路线" + p.error);
if (!p.error)
{
path = p;
currentWaypoint = 0;
}
}
private void OnDisable()
{
seeker.pathCallback -= OnPathComplete;
}
}