简单的AI追踪玩家

        本次采用的是使用碰撞箱(collider)检测玩家是否在范围内,在使用前要勾选is Trigger作为触发器来检测,而想要让敌人追踪玩家非常简单,以前我的文章中写过关于追踪子弹的实现,而敌人追踪玩家据还只需要直接向着玩家移动就行了。

        而关于路径点寻路,也就是上期写的沿指定路线移动,这里也不再过多叙述。

        然而问题在于,如果是简单的玩家进入识别范围后,玩家是位于某个墙体后面进入范围的,那么敌人也会朝向玩家运动,导致顶着墙体运动,非常奇怪。要解决这个问题,我们需要使用一种方式来赋予这个敌人一种类似视野的效果,当玩家位于障碍物后面时,敌人就无法看见玩家。

        这里我采用的方式是射线检测,当玩家进入敌人的触发器范围内后,如果敌人和玩家之间有障碍物,那么射线检测到的旧不是玩家而是第一道障碍物,只要射线未直接检测到玩家,那么就不让敌人朝向玩家运动,保持当前运动状态。

        然后,关于射线检测,有一点需要注意的是,如果你的物体射线检测是从某个有碰撞的物体内部发射的,那么射线检测到的第一个物体就会是物体本身而不是玩家或者障碍物。这里可以打开编辑器将2D物理中的<碰撞器开始的查询>(英文为Queries Start in Collider)关闭,这将会导致这个射线忽略从自身碰撞,另一个是关闭<查询命中触发器>(Queries Hit Triggers)因为这里使用的触发器检测玩家方式会导致这个射线会检测触发器,当实际开启与否得看你的需要。

        接下来是代码部分,代码有沿用上一期的指定路线寻路部分,但是有较多修改。

        属性部分:

//引用的所有属性
    [Range(0,20)]
    public float Speed;//速度

    [Range(0, 2)]
    public int Move_method;//移动方式

    public GameObject Line;//运动线路

    public float Distance;//允许距离差

    [Range(0,20)]
    public float Wait_time;//避免持续走向墙体

    private float Current_wait_time;

    private Transform[] Array_point;//路点数组

    private int index;//数组下标

    private bool Return;//往返路径需要的属性

    private GameObject Player;//保存需要追踪的玩家对象

    private bool See_Change;//射线检测值改变

    private Vector3 Position;//记录最后寻址位置

    private Rigidbody2D body;//刚体组件

    private Action action;//封装行为逻辑的函数

        这里我额外添加了寻址移动,作用为当发现玩家而玩家脱离了触发器检测范围或者射线检测被障碍物阻挡,那么就走到丢失玩家信息位置前的位置,毕竟正常来看,哪个人会因为别人躲到墙后面或者走远了就不会继续追了,不过因为移动的方式没有改变,因此敌人并不会绕开墙体走,所以为了避免卡墙,就添加当一定时间后放弃寻找,类似于很多游戏中的丢失仇恨。

        unity方法体中:

    private void Start()
    {
        //基本属性的初始化
        body = GetComponent<Rigidbody2D>();
        index = 0;
        Return = true;
        See_Change = true;
        Array_point = Line.GetComponentsInChildren<Transform>();

        //对于路径点移动的方式的初始化,采用委托的方式
        switch (Move_method)
        {
            case 0:
                action = Move_Line0;
                break;
            case 1:
                action = Move_Line1;
                break;
            case 2:
                action = Move_Line2;
                break;
            default:
                break;
        }
    }

    
    private void Update()
    {
        if(Player != null && RayCast())//追踪玩家的情况下,能射线检测到玩家,不断记录玩家的位置
        {
            Current_wait_time = 0;
            Move(Player.transform.position);
        }
        else if (Vector_Move() && See_Change)//在有过发现玩家的情况下,才能执行到此,一但达到位置除非再次发现过玩家否则不会执行
        {
            Current_wait_time += Time.deltaTime;//模拟脱离仇恨的机制,在学习2D避开障碍物移动后将修改这种防止卡墙方式
            if(Current_wait_time >= Wait_time)
            {
                See_Change = false;
                Current_wait_time = 0;
            }
            Move(Position);
        }
        else//路径移动情况下,未发现玩家,需要最后寻址的位置已经走过
        {
            Current_wait_time = 0;
            action();
        }
    }

        射线检测部分:

    private bool RayCast()
    {
        //因为物体的碰撞箱可能不会在物体的正中心,需要根据你的实际偏移来调整偏移量
        Vector2 Start_Position = transform.position;
        Start_Position.y -= 0.1f;
        Vector2 Aim_Direction = Player.transform.position;
        Aim_Direction.y -= 0.1f;
        Aim_Direction -= Start_Position;

        //射线检测玩家
        RaycastHit2D hitinfo = Physics2D.Raycast(Start_Position, Aim_Direction);
        if (hitinfo.collider != null && hitinfo.collider.GetComponent<Move_text>() != null)
        {
            //如果检测到了玩家,就存储其位置,这样当未检测到时,就执行寻址移动到上一帧丢失前的位置
            Position = hitinfo.collider.transform.position;
            return See_Change = true;
        }
        return false;
    }

        寻址移动

    private bool Vector_Move()
    {
        if (Get_Distance(Position) <= Distance)
        {
            return See_Change = false;
        }
        return true;
    }

        值得注意的一点是在玩家脱离触发器后,不要直接把玩家位置赋给Position

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.GetComponent<Move_text>() != null)
        {
            //必须得进行一次射线检测,防止因为玩家是在墙后面脱离检测范围导致物体向墙走
            RayCast();
            Player = null;
        }
    }

        最后来大致看看效果

         当然如果可以的话,你可以在最后寻址的时候让AI反复随机向几个位置移动,更加接近一种寻找玩家的感觉。

猜你喜欢

转载自blog.csdn.net/WEIWEI6661012/article/details/129914689
今日推荐