【Unity小技巧】一个脚本实现控制3D远程/近战敌人AI

最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 烘培导航地图
  • 配置敌人导航数据
  • 简单配置敌人动画
  • 敌人AI脚本
  • 完结

想了解导航的其他内容可以看我这篇文章:【Unity游戏开发教程】零基础带你从小白到超神29——导航系统

烘培导航地图

在这里插入图片描述
选中地面,设置为静态导航
在这里插入图片描述
点击烘培,可行走区域
在这里插入图片描述
选中一些障碍物,也设置为静态导航
在这里插入图片描述
选择为不适合步行
在这里插入图片描述
重新点击烘培,一些障碍物区域就不可以行走了
在这里插入图片描述

配置敌人导航数据

给敌人加导航组件
在这里插入图片描述
注意:
增大角速度,是为了让敌人旋转更加快
配置停止距离和关闭自动刹车是为了防止敌人切换为待机动画,不会滑动

简单配置敌人动画

动画基础使用:新版角色动画的具体使用
在这里插入图片描述

敌人AI脚本

零基础带你从小白到超神29——导航系统

using UnityEngine;
using UnityEngine.AI;

public class EnemyAiTutorial : MonoBehaviour
{
    NavMeshAgent agent; // 导航代理
    Animator animator;
    Transform player; // 玩家的Transform对象
    public LayerMask whatIsPlayer; // 碰撞检测所需的LayerMask
    [Header("敌人的生命值")]
    public float health;

    [Space]
    [Header("巡逻相关")]
    [Header("巡逻范围")]

    public float walkPointRange;
    bool walkPointSet;//是否设置了巡逻点
    Vector3 walkPoint;//巡逻点

    [Space]
    [Header("攻击相关")]
    [Header("攻击间隔时间")]
    public float timeBetweenAttacks;
    [Header("每次攻击时间")]
    public float timeAttack;
    [Header("攻击所使用的物体(子弹)")]
    public GameObject projectile;
    bool isAttack;
    bool alreadyAttacked;//是否已经攻击过

    [Space]
    [Header("状态相关")]
    [Header("是否是近战攻击")]
    public bool isMeleeAttack;
    [Header("远程攻击点")]
    public Transform remoteAttackPoint;
    [Header("视野范围和攻击范围")]
    public float sightRange;
    public float attackRange;
    //玩家是否在视野范围和攻击范围内
    public bool playerInSightRange;
     public bool playerInAttackRange;
    [Header("速度")]
    public float walkSpeed = 1.2f;
    public float runSpeed = 5f;
    bool isIdle;

    private void Awake()
    {
        player = GameObject.Find("Player").transform; // 查找到名为"PlayerObj"的游戏物体,并获取其Transform组件
        agent = GetComponent<NavMeshAgent>(); // 获取自身的导航代理组件
        animator = GetComponent<Animator>();
    }

    private void Update()
    {
        // 检查玩家是否在视野范围或攻击范围内
        playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
        playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
        // 根据玩家位置和状态进行相应的行为
        if (!playerInSightRange && !playerInAttackRange) Patroling();
        if (playerInSightRange && !playerInAttackRange) ChasePlayer();
        if (playerInAttackRange && playerInSightRange) AttackPlayer();
    }

    private void Patroling()
    {
        if (!walkPointSet) SearchWalkPoint(); // 如果没有设置巡逻点,则搜索巡逻点

        if (walkPointSet)
        {
            agent.speed = walkSpeed; // 将导航代理的速度设置为5
            //TODO设置巡逻速度,播放走路动画
            animator.SetBool("Walk", true);
            animator.SetBool("Run", false);
            agent.SetDestination(walkPoint); // 设置巡逻点为目标点
        }


        Vector3 distanceToWalkPoint = transform.position - walkPoint;

        // 已到达巡逻点
        if (distanceToWalkPoint.magnitude < 1f)
        {
            //TODO:播放待机动画,休息3-5秒,也可以等待机动画执行完再进行下一步
            animator.SetBool("Walk", false);
            animator.SetBool("Run", false);

            if (!isIdle)
            {
                Invoke(nameof(SetWalkPointSet), Random.Range(3, 6));
            }

            isIdle = true;
        }
    }

    void SetWalkPointSet()
    {
        isIdle = false;
        walkPointSet = false;
    }

    private void SearchWalkPoint()
    {
        // 在指定范围内随机生成一个巡逻点
        float randomZ = Random.Range(-walkPointRange, walkPointRange);
        float randomX = Random.Range(-walkPointRange, walkPointRange);

        walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);
        // SamplePosition表示判断该点是不是导航允许到达的地方
        NavMeshHit hit;
        if (NavMesh.SamplePosition(walkPoint, out hit, walkPointRange, 1))
        {
            walkPoint = hit.position;
            walkPointSet = true;
        }
    }

    private void ChasePlayer()
    {
        //判断是否在攻击
        if(isAttack) return;

        //TODO设置追击速度,播放奔跑动画
        agent.speed = runSpeed; // 将导航代理的速度设置为5
        animator.SetBool("Walk", false);
        animator.SetBool("Run", true);
        agent.SetDestination(player.position); // 设置导航代理的目标点为玩家位置
    }

    private void AttackPlayer()
    {
        // 已到达目标点附近
        if ((transform.position - player.position).magnitude < 1.5f)
        {
            // 停止移动
            agent.SetDestination(transform.position);
        } 

        if (!alreadyAttacked)
        {
            //面向玩家
            transform.LookAt(player);

            //是否是近战攻击
            if (isMeleeAttack)
            {
                animator.SetBool("Walk", false);
                animator.SetBool("Run", false);
                //TODO播放近战攻击动画
                animator.SetTrigger("Punch");
            }
            else
            {
                ///攻击代码
                Rigidbody rb = Instantiate(projectile, remoteAttackPoint.position, Quaternion.identity).GetComponent<Rigidbody>();
                rb.AddForce(transform.forward * 32f, ForceMode.Impulse);
                rb.AddForce(transform.up * 8f, ForceMode.Impulse);
                ///攻击代码结束
            }

            alreadyAttacked = true;
            Invoke(nameof(ResetAttack), timeBetweenAttacks);

            //攻击时间
            isAttack = true;
            Invoke(nameof(ResetIsAttack), timeAttack);
        }
    }

    private void ResetIsAttack()
    {
        isAttack = false;
    }

    private void ResetAttack()
    {
        alreadyAttacked = false;
    }

    public void TakeDamage(int damage)
    {
        health -= damage;

        // 如果生命值小于等于0,则摧毁自身
        //TODO: 播放死亡动画
        if (health <= 0) Invoke(nameof(DestroyEnemy), 0.5f);
    }

    private void DestroyEnemy()
    {
        Destroy(gameObject);
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, attackRange); // 在编辑器中绘制攻击范围的圆
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, sightRange); // 在编辑器中绘制视野范围的圆形
    }
}

挂载脚本,配置参数,这里以一个近战敌人为例子
在这里插入图片描述

效果
在这里插入图片描述

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《动手学深度学习(PyTorch版)》笔记4.4

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

写静态页面——魅族声学_前端页面练习

1、效果: 1、html代码: <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>魅族声学</titl…

5G时代下的融合CDN新风口

近年来&#xff0c;随着网络技术的飞速发展&#xff0c;互联网流量视频化的趋势日益明显&#xff0c;视频应用使互联网的可扩展性、可演进性、服务质量和网络安全面临诸多挑战。为克服传统IP网络在服务视频应用当中的不足&#xff0c;内容分发网络CDN被提出&#xff0c;并迅速成…

java servlet运输公司管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web运输公司管理系统是一套完善的java web信息管理系统 serlvetdaobean mvc 模式开发 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主 要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5…

Go的单元测试

开发项目过程中&#xff0c;少不了单元测试&#xff1b;下面我们认识下单元测试&#xff1a; Go 语言测试框架可以让我们很容易地进行单元测试&#xff0c;但是需要遵循五点规则。 含有单元测试代码的 go 文件必须以 _test.go 结尾&#xff0c;Go 语言测试工具只认符合这个规…

2. MySQL 多实例

重点&#xff1a; MySQL 的 三种安装方式&#xff1a;包安装&#xff0c;二进制安装&#xff0c;源码编译安装。 MySQL 的 基本使用 MySQL 多实例 DDLcreate alter drop DML insert update delete DQL select 2.5&#xff09;通用 二进制格式安装 MySQL 2.5.1&#xff…

JavaScript学习-原型和原型链

原型和原型链 示例代码 //创建一个Person类 class Person {constructor(name) {this.name name;}drink() {console.log(喝水);} } //创建一个Teacher类&#xff0c;继承Person class Teacher extends Person {constructor(name, subject) {super(name);this.subject subjec…

微信小程序 仿微信聊天界面

1. 需求效果图 2. 方案 为实现这样的效果&#xff0c;首先要解决两个问题&#xff1a; 2.1.点击输入框弹出软键盘后&#xff0c;将已有的少许聊天内容弹出&#xff0c;导致看不到的问题 点击输入框弹出软键盘后&#xff0c;将已有的少许聊天内容弹出&#xff0c;导致看不到的问…

FFMPEG解析ts流

三篇相关联的文章&#xff1a; ffmpeg下HLS解析过程-CSDN博客TS文件格式详解及解封装过程-CSDN博客 FFMPEG解析ts流-CSDN博客 一、简介 关于TS格式解析&#xff0c;可以参考《TS文件格式详解及解封装过程-CSDN博客》&#xff0c;本文主要代码部分解读。建议大家熟读iso138…

【JaveWeb教程】(30)SpringBootWeb案例之《智能学习辅助系统》的详细实现步骤与代码示例(3)员工管理的实现

目录 SpringBootWeb案例033. 员工管理3.1 分页查询3.1.1 基础分页3.1.1.1 需求分析3.1.1.2 接口文档3.1.1.3 思路分析3.1.1.4 功能开发3.1.1.5 功能测试3.1.1.6 前后端联调 3.1.2 分页插件3.1.2.1 介绍3.1.2.2 代码实现3.1.2.3 测试 3.2 分页查询(带条件)3.2.1 需求3.2.2 思路分…

电流检测电路设计方案汇总

电流检测电路设计方案&#xff08;一&#xff09; 低端检流电路的检流电阻串联到地&#xff08;图1&#xff09;&#xff0c;而高端检流电路的检流电阻是串联到高电压端&#xff08;图2&#xff09;。两种方法各有特点&#xff1a;低端检流方式在地线回路中增加了额外的线绕电…

内网穿透natapp使用教程(Linux)

我的使用场景&#xff1a;在家访问学校服务器&#xff0c;由于不在一个局域网&#xff0c;所以需要使用内网穿透&#xff0c;我使用的是natapp。需要在有局域网的时候做好以下步骤。 &#xff08;natapp官网&#xff1a;https://natapp.cn/&#xff09; 1. 下载客户端 &#x…

开发微信小程序,将图片下载到相册的方法,saveImageToPhotosAlbum怎么用

在开发微信小程序的时候&#xff0c;经常能看到小程序里面有下载按钮&#xff0c;如何将小程序中的图片下载到手机相册中那&#xff0c;下面给大家说一下怎么做&#xff0c;代码如何去写。 一、到微信小程序后台开启“用户隐私保护指引” 1.进入小程序后台&#xff0c;侧拉拉到…

第16章_网络编程(网络通信要素,TCP与UDP协议,网络编程API,TCP网络编程,UDP网络编程,URL编程)

文章目录 第16章_网络编程本章专题与脉络1. 网络编程概述1.1 软件架构1.2 网络基础 2. 网络通信要素2.1 如何实现网络中的主机互相通信2.2 通信要素一&#xff1a;IP地址和域名2.2.1 IP地址2.2.2 域名 2.3 通信要素二&#xff1a;端口号2.4 通信要素三&#xff1a;网络通信协议…

[C#]winform部署yolov5实例分割模型onnx

【官方框架地址】 https://github.com/ultralytics/yolov5 【算法介绍】 YOLOv5实例分割是目标检测算法的一个变种&#xff0c;主要用于识别和分割图像中的多个物体。它是在YOLOv5的基础上&#xff0c;通过添加一个实例分割模块来实现的。 在实例分割中&#xff0c;算法不仅…

自动化软件开发常用代码分享!

随着科技的发展&#xff0c;自动化软件开发已经成为现代企业不可或缺的一部分&#xff0c;自动化软件可以帮助企业提高生产效率、降低成本、优化业务流程。 而在自动化软件开发中&#xff0c;代码是实现这些功能的基础&#xff0c;本文将分享一些常用的自动化软件开发代码&…

苍穹外卖-前端部分(持续更新中)

d 第二种&#xff1a;cmd中输入 vue ui进入图形化界面选择npm,vue2进行创建 先将创建的Vue框架导入Vsocde开发工具 然后ctrshiftp 输入npm 点击serve将项目启动 下这种写法跨域会报错&#xff1a; 解决方法&#xff1a;

虚拟机内使用 archinstall 安装 arch linux 2024.01.01

文章目录 [toc]前言碎语安装 arch linuxArchinstall languageMirrorsLocalesDisk configurationBootloaderSwapHostnameRoot passwordUser accountProfileAudioKernelsAdditional packagesNetwork configurationTimezoneAutomatic time syncOptional repositoriesInstall 进入桌…

OceanMind海睿思入选《2023大数据产业年度创新技术突破奖》,并蝉联多项图谱

近日&#xff0c;由数据猿和上海大数据联盟主办&#xff0c;上海市经济和信息化委员会、上海市科学技术委员会指导的“第六届金猿季&魔方论坛——大数据产业发展论坛”在上海成功举行&#xff0c;吸引了数百位业界精英的参与。中新赛克海睿思作为国内数字化转型优秀厂商代表…

基于springboot+vue的校园资料分享平台(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…