Unity实现敌人沿着指定路线移动

        使用的是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)就是,所以仅做参考,实际使用需要学会简化算法的时间复杂度和空间复杂度,优化结构,节省性能开销。

        再来看看我设置的三种方式移动效果

 

        线路移动可以用于设置敌人沿着某个固定路线移动,从而产生一种巡逻的效果,当发现玩家时就退出线路移动追踪玩家,否则继续沿着路径移动。另外这些点在游戏中改变了位置时,敌人也会改变随之移动路径。

猜你喜欢

转载自blog.csdn.net/WEIWEI6661012/article/details/129866176