使用的是2D模板,但是除了增加一个Z轴的考虑,其它基本都是一样的,当然如果你的3D场景是平坦面的话几乎代码可以直接复用。
想要让敌人沿着指定路线移动,就要规定他需要移动的路点位置。
在这里,我采用的是建立一个空对象line,在再这个line对象底下一次插入空对象point,使用空对象的原因是因为我们只需要路点得到的位置,除非特殊需求,我们不需要其它的组件属性,为了便于观察,设置点的图标,确定敌人是否会沿着点位移动。
接下来,关键就是如何取得这些点位的位置了,最开始我尝试使用GetComponentsInChildren<GameObject>();拿到所有的子物体,再取得所有子物体的TransForm获得位置,但是实际上这个方法不能直接拿子物体本身,所以<>中至二级选择取TransForm就可以了,之后的部分就非常简单了,见代码。
//这个的理解难度相比于弹幕追踪要简单很多,实现难度也低很多,所以注释会比较少
public class AI_Move_line : MonoBehaviour
{
public GameObject line;//线路组
public Transform[] line_array;//所有路点位置的数组
[Range(0, 50)]
public float speed;//移动速度
[Range(0, 2)]
public int move_method;//移动循环方式
//0为从出发点开始,到终点时从起点为目标再次开始循环移动
//1为到了终点后,沿着原路返回,回到起始点后再次按路径到终点
//2为到了终点后将不再移动
private Rigidbody2D body;//刚体组件
[Range(0, 10)]
public float point_waittime;//每次到达一个位置后的的等待时间
[Range(0, 10)]
public float point_distance;//距离路点的位置容忍差
private int index;//标点位置
private bool set = true;//路径移动辅助,默认true
void Start()
{
index = 0;
body = GetComponent<Rigidbody2D>();
line_array = line.GetComponentsInChildren<Transform>();//拿到所有的路点,确定寻路位置
}
void Update()//根据选择的移动方式进行移动
{
switch (move_method)
{
case 0:
Move_line0();
break;
case 1:
Move_line1();
break;
case 2:
Move_line2();
break;
default:
break;
}
}
private float Get_Distance(Transform point)//获取物体和路点的距离
{
return Vector3.Distance(transform.position, point.position);
}
void Move_line0()//移动方式-0,这个判断格式使得此方法可以复用
{
if (Get_Distance(line_array[index]) <= point_distance && set)
{
index = (index + 1) % line_array.Length;
}
else if (Get_Distance(line_array[index]) <= point_distance && !set)
{
index--;
}
Move();
}
void Move_line1()//移动方式-1,到大最后一个点是修改set,使得line0中index从自增改为自减
{
if(index == line_array.Length - 1 && set)
{
set = false;
}
else if(index == 0 && !set)
{
set = true;
}
Move_line0();
}
void Move_line2()//判断到达终点后不再进行移动操作
{
if(index == line_array.Length -1 && Get_Distance(line_array[index]) <= point_distance)
{
return;
}
else
{
Move_line0();
}
}
void Move()//朝向目标移动
{
Vector2 rot = line_array[index].position - transform.position;
rot = rot.normalized;
Vector2 position = transform.position;
position.x += rot.x * speed * Time.deltaTime;
position.y += rot.y * speed * Time.deltaTime;
body.MovePosition(position);
}
}
line的作用就是存储路径,我们可以在编辑器界面设置好线路后,只需要将线路对象给line变量,就可以通过GetComponentsInChildren拿到所有子物体点的位置,特别要注意的一点是,这个方法还会将父物体本身的TransForm返回,如果你不想要计入这个点,可以将index起始设置为1。
另外这段代码其实很亢余,有些函数的调用判断其实可以简化的(Get_Distance)就是,所以仅做参考,实际使用需要学会简化算法的时间复杂度和空间复杂度,优化结构,节省性能开销。
再来看看我设置的三种方式移动效果
文章来源:https://www.toymoban.com/news/detail-530348.html
线路移动可以用于设置敌人沿着某个固定路线移动,从而产生一种巡逻的效果,当发现玩家时就退出线路移动追踪玩家,否则继续沿着路径移动。另外这些点在游戏中改变了位置时,敌人也会改变随之移动路径。文章来源地址https://www.toymoban.com/news/detail-530348.html
到了这里,关于Unity实现敌人沿着指定路线移动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!