686
社区成员




unity2D中实现简单的敌人AI,包括范围内自动巡逻/随机漫游、追击玩家、发动攻击
以Bat为例,作为横板视角游戏的飞行单位,它的活动范围是一个面,所以同样可以应用于俯视视角游戏中。
首先为角色对象(EnemyBat)挂上Box Collider 2D(勾选isTrigger)和脚本,为了实现随机漫游,我们需要三个坐标:MovePos
(代表bat,位置随便放)、LeftDownPos
、RightUpPos
。LeftDownPos
和RightUpPos
分别定义了移动范围的左下角和右上角。
下面这段代码位于update
中,首先让bat朝着movePos
的位置移动,接着判断bat与movePos
的距离,当二者重合时,bat会在原地等待waitTime
秒的时间,时间到了之后,重新随机设置movePos
位置(实现在后文),重置waitTime
。这样bat就朝着下一个位置移动,如此反复
transform.position = Vector2.MoveTowards(transform.position, movePos.position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, movePos.position) < 0.1f)
{
if (waitTime <= 0)
{
movePos.position = GetRandomPos();
waitTime = startWaitTime;
}
else
{
waitTime -= Time.deltaTime;
}
}
在指定范围内随机设置movePos
位置
Vector2 GetRandomPos()
{
Vector2 rndPos = new Vector2(Random.Range(leftDownPos.position.x, rightUpPos.position.x),
Random.Range(leftDownPos.position.y, rightUpPos.position.y));
return rndPos;
}
对于横板视角游戏的地面单位,他们活动一般是左右往复巡逻,同样可以用两个pos划出范围,然后在到边界时实现转身即可
这段代码位于update,moveSpots[]
存放着左右两个Pos,当达到某一Pos时,判断是左右边界,翻转角色。此处我为了省事直接用下标判断,0是右1是左。
transform.position =
Vector2.MoveTowards(transform.position, moveSpots[i].position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpots[i].position) < 0.1f)
{
if (waitTime <= 0)
{
if (i == 0)
{
transform.eulerAngles = new Vector3(0, -180, 0);
i = 1;
}
else
{
transform.eulerAngles = new Vector3(0, 0, 0);
i = 0;
}
waitTime = wait;
}
else
{
waitTime -= Time.deltaTime;
}
在游戏对象下添加一个子对象sight,包含一个盒型触发器,也就是图中外围的绿框。当玩家进入绿框时,开启追击
在sight上挂着一个脚本,用于检测触发器的触发,通过修改参数通知父对象脚本更改行为模式
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player") && other.GetType().ToString() == "UnityEngine.CapsuleCollider2D")
{
EnemyBat.isInField = true;
}
}
void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player") && other.GetType().ToString() == "UnityEngine.CapsuleCollider2D")
{
EnemyBat.isInField = false;
}
}
同样EnemyBat上挂载的脚本,在update中要做相应的判断
if(!isInField)
{
//随机漫游
transform.position = Vector2.MoveTowards(transform.position, movePos.position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, movePos.position) < 0.1f)
{
if (waitTime <= 0)
{
movePos.position = GetRandomPos();
waitTime = startWaitTime;
}
else
{
waitTime -= Time.deltaTime;
}
}
}
else
{
//追击玩家
transform.position = Vector2.MoveTowards(transform.position,
playerTransform.position,
speed * Time.deltaTime);
}
上述敌人的攻击方式是自身与玩家接触,而有些敌人是通过武器或是技能攻击玩家。这时就需要在合适的时机调用这些攻击相关函数,我此处用了一个触发器判断,实现类似sight,触发时即发动攻击。
老是打不到人
这个绿色方框就是攻击触发范围,是略小于攻击范围的,这样可提高击中目标的概率(否则刚到攻击范围就挥刀,攻击前摇时间够玩家拉开距离了)
碰到攻击范围就扣血,还是两倍
这种实现方法要求父节点(也就是角色对应的gameobject
)没有挂载Rigidbody 2D
,否则碰到子物体(攻击范围)将分别触发父、子节点的OnTriggerEnter
方法。否则结果就是:玩家碰到攻击范围的框,受到了触碰怪物身体的两倍伤害。
这个问题涉及的知识点非常细,印象深刻
在这次的项目过程中,除了基本的场景搭建,我还学到了比如制作粒子特效,伤害浮动显示,实现玩家武器,攻击判定等等,敌人AI这部份相对来说比较有意思,就拿出来讲了
以上仅仅实现了敌人的简单AI,主要为读者提供一个实现思路,还需要自行扩展