最终效果
插件下载链接:
https://download.csdn.net/download/qq_36303853/87762376
可以前往官网下载和查看开发文档
https://arongranberg.com/astar/download
导入AI插件
新建空物体,添加PathFinder组件,用在地图导航
渲染导航路径,绘制出来的蓝色部分则为可行走区域,非蓝色区域是我配置的碰撞器区域,可自行修改,如果不满意可以修改Diameter的值,控制碰撞器区域多大的范围不可行走
给敌人添加碰撞器,碰撞区域自行调整
给敌人添加AIPath组件,我们这里的2d项目,记得orientation先选择YAxisForward(for 2D games)
,如果你不想敌人旋转,可以去掉勾选Enable Rotation
常用参数 | 解释 |
---|---|
can move | 表示能否移动 |
max speed | 表示移动速度 |
rotation speed | 表示旋转速度 |
slowdown distance | 表示减速距离 |
end reached distance | 表示停止距离,表示怪物距离玩家多远的适合会停止移动 |
pick next waypint dist | 表示距离下个路径点的距离 |
Gravity | 表示重力,这里不需要重力所以选择none |
再给敌人添加AI Destination setter组件,这个是设置敌人的目标,拖入我们的玩家即可
运行效果
代码控制敌人移动,并发起攻击
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class Enemy : MonoBehaviour
{
public float startHealth = 100;//开始血量
public float health;//当前血量
public bool isDead;//是否死亡
public float damage = 10;//敌人伤害
public float hitRate = 1.0f;//攻速
private float _lastHit;//计时器
public LayerMask whatToHit;//可以攻击哪个图层
private float hitDistance = 2.0f;//攻击距离
[Header("ai导航属性")]
private AIPath aiPath;
private Transform target; //目标
private void Start()
{
aiPath = GetComponent<AIPath>();
target = GameObject.FindGameObjectWithTag("Player").transform;
health = startHealth;
}
private void Update()
{
if (target == null) return;
aiPath.destination = target.position;//敌人移动的目标位置
if (aiPath.reachedDestination)//是否抵达目标位置
{
//发起攻击
if (Time.time > _lastHit + 1 / hitRate)
{
Hit();
_lastHit = Time.time;
}
}
}
//攻击
void Hit()
{
//怪物朝向
Vector3 targetDirection = (target.position - transform.position).normalized;
//射线 aiPath.endReachedDistance表示抵达终点的距离
RaycastHit2D hit2D = Physics2D.Raycast(transform.position, targetDirection, aiPath.endReachedDistance + hitDistance, whatToHit);
if (hit2D.collider != null)
{
Debug.Log(damage);
//造成伤害
PlayerController playerController = hit2D.collider.GetComponent<PlayerController>();
playerController?.TakeDamage(damage);
}
}
}
更加复杂的代码控制
using UnityEngine;
using Pathfinding;
public class MyAIMove : MonoBehaviour
{
private Seeker mSeeker; // 寻路组件
private List<Vector3> mPathPointList; // 路径点列表
private int mCurrentIndex = 0; // 当前路径点索引
void Start()
{
mSeeker = GetComponent<Seeker>(); // 获取Seeker组件
}
void Update()
{
// 当鼠标左键点击时
if (Input.GetMouseButtonDown(0))
{
// 获取鼠标点击位置,并转换为世界坐标
Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
target.z = 0; // 保证z轴为0(2D场景)
// 创建路径
CreatePath(target);
// 移动角色
Move();
}
}
private void Move()
{
// 如果路径点列表为空或者当前索引超出范围,直接返回
if (mPathPointList == null || mCurrentIndex >= mPathPointList.Count)
return;
// 如果当前位置与目标路径点的距离大于0.2f,则继续移动
if (Vector2.Distance(transform.position, mPathPointList[mCurrentIndex]) > 0.2f)
{
// 计算移动方向
Vector3 dir = (mPathPointList[mCurrentIndex] - transform.position).normalized;
// 根据方向移动角色,这里的20是移动速度,Time.deltaTime是每帧的时间间隔
transform.position += dir * Time.deltaTime * 20;
}
else
{
// 如果已经到达当前路径点,则切换到下一个路径点
if (mCurrentIndex == mPathPointList.Count - 1)
return;
mCurrentIndex++;
}
}
private void CreatePath(Vector3 target)
{
mCurrentIndex = 0; // 重置当前路径点索引为0
// 开始寻路,从当前位置到目标位置
mSeeker.StartPath(transform.position, target, path =>
{
// 寻路完成后,将路径点存入路径点列表
mPathPointList = path.vectorPath;
});
}
}
目前人物的移动会非常生硬,在人物身上挂载一个Simple Smooth组件,不用做任何修改,我们的移动就变得顺滑了
其他
还有一个Unity2d自动寻路插件NavMeshPlus,需要的可以去了解
git地址:https://github.com/h8man/NavMeshPlus
区别
A*Pathfinding插件和NavMeshPlus插件都是Unity的导航网格相关的插件。它们之间的区别主要体现在以下几个方面:
1.算法原理:A* Pathfinding插件使用的是A*算法来搜索最短路径,而NavMeshPlus插件使用的是Unity自带的导航网格系统来计算路径。
2.功能特点:A* Pathfinding插件提供了大量的路径搜索和寻路算法,同时还提供了寻路障碍物躲避、寻路优化等功能;而NavMeshPlus插件则主要关注于优化Unity的导航网格系统,提供了更高效更准确的表面剖分、NavMesh配置和障碍物遮蔽等功能。
3.使用成本:A* Pathfinding插件需要进行额外的配置和调试,而NavMeshPlus插件则更加易用,直接在Unity中就能够完成操作。
基于以上区别,推荐的使用场景为:如果您需要复杂的寻路算法、路线优化或存在大量的寻路单位,建议使用A*Pathfinding插件;如果您只需要简单的寻路算法,或需要优化现有导航网格的性能,建议使用NavMeshPlus插件。
总而言之,这两个插件都是非常优秀的导航网格相关插件,具体的使用需根据实际需求进行选择。
为啥大量的寻路单位推荐使用A*Pathfinding?
A* Pathfinding插件采用了基于图的最短路径搜索算法,相比于Unity的导航网格系统来说,对于大量的寻路单位能够更快速地搜索到最短路径,避免了因为单位数量增加而导致导航网格系统计算路径的效率下降的问题。
A* Pathfinding插件还提供了很多高级算法,如流形平滑、局部避障等算法,能够对路径进行优化或者避免行进时的碰撞,尤其适用于复杂的场景以及大量单位的游戏中。
此外,A* Pathfinding可以配置多个线程来计算寻路,能够进一步提高性能。而Unity的导航网格是单线程计算,一旦出现大量的寻路单位,计算时间会成倍增加。
因此,对于场景中存在大量的寻路单位的游戏,推荐使用A* Pathfinding插件。