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

news2024/11/14 9:45:31

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

敌人攻击玩家

  • 敌人检测玩家
    • 目标
    • 思路-碰撞检测的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;
    }
}

效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2240089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx代理后jsp如何获取http协议

1. nginx配置增加返回协议类型&#xff08;http或https&#xff09; location / {proxy_set_header X-Forwarded-Proto $scheme; } 2. 修改jsp配置 原jsp配置&#xff1a; <%String basePath request.getScheme()"://"request.getServerName()":"r…

#渗透测试#SRC漏洞挖掘#蓝队基础之网络七层杀伤链01

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

uni-app移动端与PC端兼容预览PDF文件

过程遇到的问题 1、如果用的是最新的版本的pdfjs的话&#xff0c;就会报Promise.withResolvers 不是一个方法的错误&#xff0c;原因是Promise.withResolvers是ES15新特性&#xff0c;想了解可参考链接&#xff0c;这里的解决方案是将插件里的涉及到Promise.withResolvers的地…

HBase使用create创建表时报错ERROR: KeeperErrorCode = NoNode for /hbase/master

场景模拟 1. 正常情况 模拟ERROR: KeeperErrorCode NoNode for /hbase/master错误场景。 正常情况下创建hbase表如下图所示。 2. 删除hbase集群的zk节点 进入zookeeper客户端。 zkCli.sh删除hbase的zk节点。 deleteall /hbase退出zookeeper客户端。 quit3. 重启hbase集…

前端web

题目&#xff1a;制作带有下拉悬停菜单的导航栏 效果图 一、先制作标签 <body> <div id"menu"> <div id"container"> <div class"item">游戏1 <div class…

实测运行容器化Tomcat服务器

文章目录 前言一、拉取Tomcat 9.0镜像二、运行容器化Tomcat服务器三、访问Tomcat官网首页测试 总结 前言 运行容器化Tomcat服务器&#xff0c;首先确保正确安装docker&#xff0c;并且已启动运行&#xff0c;具体安装docker方法见笔者前面的博文《OpenEuler 下 Docker 安装、配…

PHP图书绘本借阅管理系统小程序源码

&#x1f4da; 图书绘本借阅管理系统&#xff1a;打造孩子的阅读乐园 &#x1f4da; &#x1f3f7;️ 引言&#xff1a;为什么我们需要图书绘本借阅管理系统&#xff1f; 在孩子的成长旅程中&#xff0c;阅读是不可或缺的一部分。然而&#xff0c;面对琳琅满目的图书和绘本&a…

炼码LintCode--数据库--基础语法--刷题笔记_01

目录 炼码LintCode数据库入门级别的笔记未完待续~~~ 炼码LintCode 数据库 入门级别的笔记 笔记如下&#xff0c;把所有涉及到的入门级别的知识点简单总结了一下。 以及一点点举一反三的写法。 增 INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);批量增 INSERT INT…

【含开题报告+文档+PPT+源码】基于SpringBoot和Vue框架的棋谱管理系统

开题报告 随着信息技术的飞速发展&#xff0c;尤其是互联网、大数据和人工智能等技术的进步&#xff0c;棋类运动在全球范围内得到了更广泛的推广和深入的研究。棋谱作为棋类运动的重要组成部分&#xff0c;是记录对弈过程、分析棋艺、传承棋道文化的关键载体。然而&#xff0…

three.js 杂记

clip&#xff1a; 1&#xff1a; 着色器 #ifdef USE_CLIP_DISTANCE vec4 worldPosition modelMatrix * vec4( position, 1.0 ); gl_ClipDistance[ 0 ] worldPosition.x - sin( time ) * ( 0.5 ); #endif gl_Position projectionMatrix * modelViewMatrix * vec4( positio…

并发基础:(淘宝笔试题)三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串【举一反三】

🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀 🌟 在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。 💡 无论你是刚刚踏…

C# 异步Task异常处理和堆栈追踪显示

Task的问题 在C#中异步Task是一个很方便的语法&#xff0c;经常用在处理异步&#xff0c;例如需要下载等待等方法中&#xff0c;不用函数跳转&#xff0c;代码阅读性大大提高&#xff0c;深受大家喜欢。 但是有时候发现我们的异步函数可能出现了报错&#xff0c;但是异常又没…

ssm102“魅力”繁峙宣传网站的设计与实现+vue(论文+源码)_kaic

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;“魅力”繁峙宣传网站系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了“魅力”繁峙宣传网站系统的发展&#x…

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并--封装到存储过程中

MySQL技巧之跨服务器数据查询&#xff1a;基础篇-A数据库与B数据库查询合并–封装到存储过程中 我们的最终目的是什么&#xff1f;当然的自动执行这些合并操作&#xff01; 上一篇 MySQL技巧之跨服务器数据查询&#xff1a;基础篇-A数据库与B数据库查询合并 我们已经知道怎么合…

短视频新纪元:AI数字人重塑视频运营格局

步入2024年&#xff0c;AI数字人技术如同一股不可忽视的力量&#xff0c;正深刻影响着视频运营的每一个角落。据行业权威机构艾媒咨询的统计数据显示&#xff0c;2023年&#xff0c;数字人相关企业注册数量激增948家&#xff0c;增长率高达68%&#xff0c;这一数据直观反映了数…

Ajax 获取进度和中断请求

HTML加入一些内容方便看效果和做交互&#xff1a; <div><p>当前传输进度&#xff1a;<span id"progress">0%</span></p><button id"send">发送</button><button id"btn">中断</button> …

ctfshow-web入门-SSTI(web361-web368)上

目录 1、web361 2、web362 3、web363 4、web364 5、web365 6、web366 7、web367 8、web368 1、web361 测试一下存在 SSTI 注入 方法很多 &#xff08;1&#xff09;使用子类可以直接调用的函数来打 payload1&#xff1a; ?name{{.__class__.__base__.__subclasses__…

Python学习从0到1 day28 Python 高阶技巧 ⑤ 多线程

若事与愿违&#xff0c;请相信&#xff0c;上天自有安排&#xff0c;允许一切如其所是 —— 24.11.12 一、进程、线程 现代操作系统比如Mac OS X&#xff0c;UNIX&#xff0c;Linux&#xff0c;Windows等&#xff0c;都是支持“多任务”的操作系统。 进程 进程&#xff1a;就…

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战

目录 前言 一、原始的处理办法 1、使用Set方法来转换 2、使用构造方法转换 二、基于ModelMapper的动态转换 1、ModelMapper简介 2、集成到项目中 3、Shapefile属性读取 三、总结 前言 在现代软件开发中&#xff0c;尤其是在多层架构中&#xff0c;经常需要将数据从一个…

2024版本IDEA创建Sprintboot项目下载依赖缓慢

目录 步骤一&#xff1a;在IDEA中搜索Maven(双击shift) 步骤二&#xff1a;找到Maven下的settings.xml文件修改镜像 ​编辑 ​编辑​编辑 步骤三&#xff1a;用VScode打开settings.xml文件修改镜像 ​编辑 步骤一&#xff1a;在IDEA中搜索Maven(双击shift) 步骤二&#xff…