unity2D学习(10)创建敌人、为敌人编写简单的AI

1 创建敌人

按照之前创建Player角色的方法,一样创建出敌人,并为角色添加刚体、碰撞、动画。具体可以参考我之前的unity2D学习(4)(5),具体的细节就不放在这里了。

素材包里面有三种敌人(crab、jumper、octopus),我选择crab来做示范动画状态转移。把Animation新建在Asserts->Animation->Enemies->Crab里面,其它类型的敌人以此类推。

参数判断:

  • Walk->Idie:speed小于0.01f
  • Idie->Walk:speed大于0.01f

2 为敌人设置简单ai

我的想法:如果Player角色出现在某一范围内,敌人就会朝玩家走去碰撞,然后走到边缘就会停下来。因为我后面想写一个玩家碰到敌人就会受伤的效果,所以我希望敌人会主动去碰撞玩家。

思路:

  • 敌人判断Player是否是在敌人的某个范围内:可以用Physics2D.OverlapCircle,来判断角色的碰撞体是否在圆形范围里面,然后根据Player在敌人左边还是右边来改变方向。

利用Physics2D.OverlapCircle判断玩家是否进入视野,和上一章unity2D学习(9)中判断碰墙的方法一样。

但是这次有点不同就是,如果用Collider2D类型来获取Physics2D.OverlapCircle就可以得到碰撞对象Collider2D,上一章里面使用Bool类型来获取得到就是“是否碰撞到”。还有需要为Player玩家设置一个Layer层来做判断用。

    Collider2D isPlayerView()//判断玩家是否进入了视野
    {
        return Physics2D.OverlapCircle((Vector2)transform.position, collisionRadius,playerLayer);//判断是否碰到玩家
    }

利用获取的Collider2D类型来判断敌人在玩家的那个方向。但是要注意敌人的动画的朝向初始是朝向左边的和主角不一样。敌人初始的横向向量虽然是正,但是动画的朝向起始对应的是左边。

    void AccordingDirectionFlip(Collider2D playerColl)//根据玩家是否出现在视野中,安排敌人转向
    {
        if (playerColl != null)//如果玩家出现视野中
        {
            int direction;
            if (playerColl.transform.position.x < transform.position.x)
            {
                direction = -1;//玩家在敌人的左边
            }
            else
            {
                direction = 1;//玩家在敌人的右边
            }
            if (direction != face)//表示方向不一致
            {
                //Debug.Log(direction);
                Flip();
            }
        }
    }
    void Flip()//翻转角色方向
    {
        face = (face == 1) ? -1 : 1;
        transform.localScale = new Vector2(face*(-1), 1);//乘-1是因为初始动画朝向是朝着左边的,但是初始坐标却是1,是相反的
    }
  • 敌人跟随Player会走到边缘,需要停下:用射线Physics2D.Raycast来判断是否走到了边缘。

Physics2D.Raycast介绍

作用:检查对撞机是否落在射线上。

public static RaycastHit2D Raycast(Vector2 origin, Vector2 direction, float distance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, float minDepth = -Mathf.Infinity, float maxDepth = Mathf.Infinity);

origin二维空间中射线起源的点
direction表示射线方向的向量
distance投射射线的最大距离
layerMask检测的特定Layer的对象
minDepthz轴大于或等于此值的对象
maxDepthz轴小于或等于此值的对象

设置Physics2D.Raycast的射线方向的向量为45°(斜着向下),然后检测的特殊Layer层为之前创建的Ground的Layer(之前TileMap的Layer层),然后起始源点为敌人自己的坐标。

    涉及到的变量
    Vector2 down = new Vector2(0, -1);//控制射线角度的向量
    private float radialLength = 1.5f;//射线的长度
    beg = transform.position;//射线起点,这个要每帖更新
    核心代码
    bool isBorder()//判断是否已经抵达边境
    {
        //也可以采用Debug的方式可视化射线
        //Debug.DrawLine(beg, beg + (new Vector2(face, 0) + down) * radialLength, Color.red);
        if (!Physics2D.Raycast(beg,new Vector2(face,0)+down, radialLength, LayerMask.GetMask("Ground")))//抵达边境
        {
            return true;
        }
        return false;
    }

这种方法射线和圈不好调整,为了方便调整参数,绘制辅助线来可视化。(具体代码看文章的末尾)

3 总代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnamyController : MonoBehaviour {

    private Rigidbody2D rig;//刚体
    private Animator Anim;//动画
    [Header("Layers")]
    public LayerMask playerLayer;//用来开启layer
    [Space]
    [Header("Collision")]
    private Collider2D coll;//碰撞器
    [SerializeField] private float collisionRadius = 5f;//检测碰撞半径
    Vector2 beg;//射线起点
    Vector2 down = new Vector2(0, -1);//控制射线角度的向量
    [SerializeField] private float radialLength = 1.1f;//射线的长度
    [Space]
    [Header("Speed")]
    private float moveSpeed = 100f;//移动速度
    [SerializeField] private float face;//朝向
    
    void Start () {
        rig = GetComponent<Rigidbody2D>();//获取刚体组件
        Anim = GetComponent<Animator>();//获取动画组件
        coll = GetComponent<Collider2D>();//获取碰撞器
        face = -1;//初始朝向是负的,和角色不同的地方,face-1代表朝向左边
        playerLayer = 1 << 9;//把玩家Layer放在Layer9
    }

    void FixedUpdate()
    {
        beg = transform.position;
        Collider2D playerColl = isPlayerView();
        if (isBorder())//是否到边缘
        {
            Debug.Log("hello");
            rig.velocity = new Vector2(0,0);
            AccordingDirectionFlip(playerColl);
        }
        else //不到边缘就可以移动
        {
            AccordingDirectionFlip(playerColl);
            Move();
        }
    }

    void AccordingDirectionFlip(Collider2D playerColl)//根据玩家是否出现在视野中,安排敌人转向
    {
        if (playerColl != null)//如果玩家出现视野中
        {
            int direction;
            if (playerColl.transform.position.x < transform.position.x)
            {
                direction = -1;//玩家在敌人的左边
            }
            else
            {
                direction = 1;//玩家在敌人的右边
            }
            if (direction != face)//表示方向不一致
            {
                //Debug.Log(direction);
                Flip();
            }
        }
    }
    void Flip()//翻转角色方向
    {
        face = (face == 1) ? -1 : 1;
        transform.localScale = new Vector2(face*(-1), 1);//乘-1是因为初始动画朝向是朝着左边的,但是初始坐标却是1,是相反的
    }

    bool isBorder()//判断是否已经抵达边境
    {
        //也可以采用Debug的方式可视化射线
        //Debug.DrawLine(beg, beg + (new Vector2(face, 0) + down) * radialLength, Color.red);
        if (!Physics2D.Raycast(beg,new Vector2(face,0)+down, radialLength, LayerMask.GetMask("Ground")))//抵达边境
        {
            return true;
        }
        return false;
    }

    Collider2D isPlayerView()//判断玩家是否进入了视野
    {
        return Physics2D.OverlapCircle((Vector2)transform.position, collisionRadius,playerLayer);//判断是否碰到地面
    }

    void Move()//左右移动
    {
        rig.velocity = new Vector2(face*moveSpeed * Time.deltaTime, rig.velocity.y);//输入x,y向量,数值*方向
    }

    void ChangeAnimator()//动画状态转换
    {
        Anim.SetFloat("speed", Mathf.Abs(rig.velocity.x));//速度是向量
    }

    void OnDrawGizmos()//绘制辅助线
    {
        Gizmos.color = Color.red;//辅助线颜色
        Gizmos.DrawWireSphere((Vector2)transform.position, collisionRadius);//绘制射线
        Gizmos.DrawLine((Vector2)transform.position, (Vector2)transform.position+(new Vector2(face, 0) + down)*radialLength);//绘制圆形
    }

}

 

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于Unity自动生成敌人Unity2D AI敌人自动追踪的问题,我可以继续提供一些建议。 对于自动生成敌人,我们可以使用Unity中的预制体(Prefab)来实现。具体地说,你可以在项目中创建一个敌人预制体,包含敌人的模型、动画、碰撞体、脚本等元素。然后,你可以在场景中放置一个空对象作为敌人生成器,编写脚本来实现自动生成敌人的功能。 在脚本中,你可以使用Instantiate方法来生成敌人实例。具体地说,你可以将敌人预制体作为参数传入,生成一个新的敌人实例,并设置它的初始位置、属性等信息。你可以使用Random类来随机生成敌人的位置和属性,使得每次生成敌人都不同。 对于敌人的自动追踪,你可以使用Unity中的NavMeshAgent组件来实现。具体地说,你可以为敌人添加一个NavMeshAgent组件,使它能够在场景中自动寻路。然后,你可以编写代码来实现敌人的追踪行为,例如让敌人朝向玩家并向其移动。 除此之,你还可以为敌人添加视野范围、攻击距离等限制,使得敌人只有在一定范围内才会追踪玩家,并只有在一定距离内才会攻击玩家。你可以使用Collider组件和Raycast来实现这些限制。 总的来说,Unity提供了很多方便的工具和功能,可以帮助你实现自动生成敌人AI追踪等功能。如果你需要更具体的代码实现或者有其他问题,可以继续向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值