欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > Unity3D学习FPS游戏(12)敌人检测和攻击玩家

Unity3D学习FPS游戏(12)敌人检测和攻击玩家

2024/11/15 1:51:25 来源:https://blog.csdn.net/qq_40306845/article/details/143556157  浏览:    关键词:Unity3D学习FPS游戏(12)敌人检测和攻击玩家

前言:上一篇实现了敌人能动,有了点乐趣,但是敌人和玩家没什么对抗性。本篇将实现敌人追击玩家,并攻击玩家。

敌人攻击玩家

  • 敌人检测玩家
    • 目标
    • 思路-碰撞检测的Trigger触发
    • 实现
  • 敌人攻击
    • 目标
    • 思路-模仿玩家发射子弹的思路
    • 实现
  • 效果

敌人检测玩家

目标

想法是这样的,玩家进入到敌人某个范围内,被敌人检测到后敌人会停下。
等玩家走后,敌人会继续原本终止的路径。

思路-碰撞检测的Trigger触发

还记得之前博客Unity3D学习FPS游戏(10)子弹攻击敌人掉血(碰撞检测)提到的碰撞检测吗?要用实现敌人检测玩家的原理也是一样的,只不过我们不需要碰撞了。

之前提到过碰撞检测有两种:Collision碰撞和Trigger触发。其中Collision碰撞是会有碰撞效果的,而Trigger触发则没有。

而敌人检测玩家就可以用没有碰撞的“Trigger触发”来检测。

回顾一下Trigger触发:

  • 函数:OnTriggerEnter/OnTriggerStay/OnTriggerExit
  • 效果:不会发生物体碰撞,也不会受到重力等物理作用力的影响,双方会直接穿过。
  • 条件:双方都有Collider,至少有一个运动的物体有Rigidbody。至少有一个碰撞体勾选IsTrigger。

目前,子弹有Colider且运动带有刚体,而玩家的Character Controller具备碰撞体(Collider)特性。

实现

给敌人构建一个检测范围,为其添加一个Sphere Collider球型的碰撞器,勾上IsTrigger就是触发器了。
在这里插入图片描述
调整检测范围,也就是Sphere Collider的Radius半径,我设置为了5。
在这里插入图片描述
编写代码思路,在检测到了玩家,就停下来攻击,并且不停面向玩家(为后面发射子弹做准备),等玩家离开视野后继续原本中断的路径。
需要编写OnTriggerEnter/OnTriggerStay/OnTriggerExit三个部分。
OnTriggerEnter检测到玩家进入范围的时候,停止移动;
OnTriggerStay玩家一直在检测范围内的时候,不停朝向玩家;
OnTriggerExit检测到玩家离开范围的时候,继续走原本的路径。

[Header("攻击数值")]
private Transform player;// 获取玩家坐标
private bool isFire;// 发射状态
void Start()
{isFire = false;// 初始不发射player = GameObject.Find("Player").transform;// 获取玩家位置
}
void Update()
{// 不在开火状态;如果路径已经算好了,而且到达目标位置很近if (!isFire&&!enemyAgent.pathPending&&enemyAgent.remainingDistance<0.1f){SetNextDestination();}
}
private void OnTriggerEnter(Collider collision)
{if (collision.gameObject.CompareTag("Player")){isFire = true;enemyAgent.isStopped = true;}
}
private void OnTriggerStay(Collider collision)
{if (collision.gameObject.CompareTag("Player")){LookAtPlayer();}
}
private void OnTriggerExit(Collider collision)
{if (collision.gameObject.CompareTag("Player")){enemyAgent.isStopped = false;isFire = false;}
}
// 朝向玩家
private void LookAtPlayer()
{// transform.LookAt(player);// 可以替代Vector3 direction = (player.position - transform.position).normalized;Quaternion lookRotation = Quaternion.LookRotation(direction);transform.rotation = lookRotation;
}

敌人攻击

目标

目前我们的敌人已经可以检测到玩家了,现在敌人要学会攻击玩家,朝着玩家发射子弹!
在玩家到检测范围内的时候,朝着玩家不停发射子弹。

思路-模仿玩家发射子弹的思路

发射子弹的思路,其实我们之前就已经做过了,在博客武器发射子弹和对象池优化发射子弹中。和之前写玩家发射子弹的思路一样,只不过这里敌人没有武器模型了,所以Enemy的WeaponController我们可以直接挂载在敌人身上。

类似与玩家的WeaponController,我们可以写一个类似的EnemyWeaponController,只不过发射子弹的信号不再是鼠标输入,而是EnemyController中检测到玩家。另外,敌人子弹是没有弹夹限制。逻辑比之前玩家武器控制简单很多。

实现

EnemyWeaponController
在敌人预制体下面,设置一个子弹发射点用来作为发射子弹的起始位置,记得不要碰到敌人本身的碰撞体不然会有碰撞。
在这里插入图片描述

新建一个EnemyWeaponController,按照之前玩家发射子弹的代码思路改写,只是发射子弹不再是鼠标输入控制了;子弹也是不限额的,所以并没有弹夹这一说。

子弹还是用之前的玩家子弹的预制体,但是音效改一下,免得和玩家混了。

[Header("子弹数值")]
public Transform shootPoint;// 子弹发射位置
public GameObject bullet;// 子弹预制体
public float shootInterval = 2F;// 子弹间隔时间
private bool isFire;// 发射状态public int bulletNum = 20;// 对象池大小
private ObjectPool<GameObject> bulletPool;// 子弹对象池[Header("音效")]
public AudioSource shootAudio;// 发射音效private void Awake()
{bulletPool = new ObjectPool<GameObject>(CreateBullet, BulletOnGet, BulletOnRelease, BulletOnDestory, true, 10, bulletNum);// 对象池构建
}GameObject CreateBullet()
{GameObject obj = Instantiate(bullet, shootPoint);obj.GetComponent<BulletController>().characterType = CharacterType.Enemy;obj.GetComponent<BulletController>().bulletPool = bulletPool;return obj;
}void BulletOnGet(GameObject obj)
{obj.GetComponent<BulletController>().BulletReset();obj.gameObject.SetActive(true);
}void BulletOnRelease(GameObject obj)
{obj.gameObject.SetActive(false);
}void BulletOnDestory(GameObject obj)
{Destroy(obj);
}
// 开始攻击
public void StartFire()
{StartCoroutine("Shoot");
}
// 停止攻击
public void StopFire()
{StopCoroutine("Shoot");
}
// 发射子弹协程
IEnumerator Shoot()
{while (true){GameObject newBullet = bulletPool.Get();// 生成子弹if (shootAudio)// 发射音效shootAudio.Play();yield return new WaitForSeconds(shootInterval);}
}

在这里插入图片描述
EnemyController
让EnemyController调用WeaponController,在原本敌人控制代码的OnTriggerEnter部分开始攻击,OnTriggerExit部分停止攻击。

private void OnTriggerEnter(Collider collision)
{if (collision.gameObject.CompareTag("Player")){isFire = true;enemyAgent.isStopped = true;this.GetComponent<EnemyWeaponController>().StartFire() ;}
}
private void OnTriggerExit(Collider collision)
{if (collision.gameObject.CompareTag("Player")){this.GetComponent<EnemyWeaponController>().StopFire();enemyAgent.isStopped = false;isFire = false;}
}

效果

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com