这节实现敌人AI的效果
为了保证代码的复用性,所以我们这里创建一个敌人父类,之后所有的敌人类都继承之这个敌人父类
先创建一个敌人父类脚本,命名为Enemy
然后简单写一下Enemy代码
这里运用了虚函数,函数前面加上visual表示这个函数是虚函数。这里简单说一下什么是虚函数
虚函数是面向对象语言中多态性的重要实现. 当一个函数方法在声明时, 前面带了virtual关键字, 这个函数就是一个虚函数. 它与非虚函数的主要区别在于它的实现可以在派生类中进行重写(override)(非强制要求). 重写后的函数一样也是虚函数, 当一个类或其基类中存在虚函数后就不允许出现同名, 返回值, 参数类型个数相同的非虚函数。
想仔细了解的话可以找一些文章看,这里就不赘述了。
然后我们创建玩敌人父类之后我们就要创建敌人了
我们先在Hierarchy栏创建一个空组件命名为Enemies,表示敌人集合,然后创建一个空的子组件命名为Enemy_Frog,剩下的操作这里就不赘述了,和角色的创建是一样的,我们这里选择角色素材包那里的青蛙
不过记得改变它的图层,改成之前创建的Enemy,不然会显示不出来
同样添加collider和Rigidbody
然后就是让敌人动起来
我们给敌人添加一下动画,和人物一样,这里不再赘述,为了方便管理,我们在Animation文件夹里新建一个文件夹Enemy来保存我们敌人的动画资源
这里我们只做了idle和run的动画即可,然后我们在Animator设置动画间的转换
用一个bool变量控制即可,run为true时切换成run动画,run为false切换成idle动画
然后我们设置一下敌人移动的边界,这个和角色检测是否碰到地面给角色添加一个checkground是一样的操作,我们给Enemy_Frog添加两个空组件,分别命名为left和right,分别表示青蛙可以移动的左右边界,然后我们调整一下位置
然后我们给Enemy_Frog写一下脚本来控制它的行动,新建一个C#文件之后直接拖给Enemy_Frog即可
我们打开脚本,照例先获得collider,rigidbody等引用,注意Enemy_Frog要继承Enemy类,而且重载了虚函数Start,所以Start函数前面要加上override
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Frog : Enemy
{
private Collider2D coll;
private Rigidbody2D rb;
public int speed;
//---------上面照旧----------
public Transform left, right;//左边边界的引用
private float leftMargin, rightMargin;//Frog可以移动的左右边界
private bool faceRight=true;//开始青蛙是面向右的
protected override void Start()
{
base.Start();//调用父类的Start函数
coll = GetComponent();
rb = GetComponent();
//分别获得左右边界位置的x轴的大小
leftMargin = left.position.x;
rightMargin = right.position.x;
//防止左边边界跟随敌人移动,获得后直接销毁
Destroy(left.gameObject);
Destroy(right.gameObject);
}
void Update()
{
Movement();
}
//基础移动
void Movement()
{
//如果面向右
if(faceRight)
{
anim.SetBool("run", true);
rb.velocity = new Vector2(speed, rb.velocity.y);
//当敌人超过右边界时
if (transform.position.x > rightMargin)
{
rb.velocity = new Vector2(0, 0);
transform.localScale = new Vector3(-1, 1, 1);
faceRight = false;
}
}
else
{
anim.SetBool("run", true);
rb.velocity = new Vector2(-speed, rb.velocity.y);
//当敌人越过左边界时
if(transform.position.x rightMargin)
{
rb.velocity = new Vector2(0, 0);
transform.localScale = new Vector3(-1, 1, 1);
faceRight = false;
}
}
else
{
anim.SetBool("run", true);
rb.velocity = new Vector2(-speed, rb.velocity.y);
//当敌人越过左边界时
if(transform.position.x 0)
{
isJump = true;
}
}
private void FixedUpdate()
{
isGround = Physics2D.OverlapCircle(groundCheck.position, 0.1f, ground);
if(!isHurt)
{
Movement();
}
Jump();
SwitchAnim();
}
//基础移动
void Movement()
{
float horizontal = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);//设置x轴的移动
//设置角色的转向问题
if (horizontal != 0)
{
transform.localScale = new Vector3(horizontal, 1, 1);
anim.SetBool("run", true);
}
else
anim.SetBool("run", false);
}
//跳跃
void Jump()
{
//如果在地面设置二段跳
if (isGround)
{
jumpCount = 2;
}
//按下跳跃键且在地面上
if (isJump && isGround)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
jumpCount--;
isJump = false;
}
//按下跳跃键且不在地面上且jumpCount大于0
else if (isJump && !isGround && jumpCount > 0)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
jumpCount--;
isJump = false;
}
}
//切换动画
void SwitchAnim()
{
//如果在下落状态
if (rb.velocity.y < 0 && !isGround)
{
anim.SetBool("fall", true);
anim.SetBool("jump", false);
}
//如果在跳跃状态
if (!isGround && rb.velocity.y > 0)
{
anim.SetBool("jump", true);
}
//如果人物受击
else if (isHurt)
{
anim.SetBool("hurt", true);
if (Mathf.Abs(rb.velocity.x) < 0.1f)
{
anim.SetBool("hurt", false);
isHurt = false;
}
}
//如果在地面上
else if (coll.IsTouchingLayers(ground))
{
anim.SetBool("fall", false);
}
}
//判断是否碰到物品
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag=="Collection")
{
Destroy(collision.gameObject);
cherries++;
cherryText.text = "樱桃:" + cherries;
}
}
//消灭敌人
private void OnCollisionEnter2D(Collision2D collision)
{
//判断是否碰到敌人
if(collision.gameObject.tag=="Enemy")
{
//消灭敌人
Enemy enemy = collision.gameObject.GetComponent ();//获得敌人父类引用
if(anim.GetBool("fall"))//判断是否下落跳到敌人头上消灭敌人
{
enemy.Death();//调用父类函数
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
anim.SetBool("jump", true);
}
//如果人物在敌人的左边
else if(transform.position.xcollision.gameObject.transform.position.x)
{
rb.velocity = new Vector2(8, rb.velocity.y);
isHurt = true;
}
}
}
}
如有错漏之处,欢迎指正!