Unity自学之旅05
Unity自学之旅05
- Unity学习之旅⑤
- 📝 AI基础与敌人行为
- 🥊 AI导航
- 理论知识(基础)
- 开始实践
- 🎃 敌人游戏机制
- 追踪玩家
- 攻击玩家
- 子弹碰撞
- 完善游戏失败条件
- 🤗 总结归纳
Unity学习之旅⑤
📝 AI基础与敌人行为
🥊 AI导航
理论知识(基础)
一、导航系统的基本组件
- NavMesh(导航网格):
- NavMesh 是 Unity 中 AI 导航的基础,它是一个表示可行走区域的网格。它将场景中的可行走表面(如地面、楼梯等)进行三角剖分,形成一个平面的网格,用于代理(Agent)导航。
- 生成 NavMesh 的步骤:
- 首先,需要将场景中的几何体标记为静态(Static),以便 Unity 可以将它们纳入 NavMesh 的计算。
- 然后,打开 Navigation 窗口(Window -> AI -> Navigation),在 Bake 选项卡中调整设置,例如 Agent Radius(代理半径)、Agent Height(代理高度)等,这些设置决定了代理在场景中占用的空间大小和形状。
- 点击 Bake 按钮,Unity 会生成 NavMesh,显示为场景中的蓝色网格。
- NavMeshAgent(导航网格代理):
- 这是附加在游戏对象上的组件,用于让对象在 NavMesh 上移动。
- 主要属性:
- Speed:代理的移动速度。
- Acceleration:代理的加速度。
- Stopping Distance:距离目标多远时停止移动。
- Radius:代理的半径,用于避障和计算可行走区域。
- Height:代理的高度,决定了代理可以通过的最小空间高度。
- NavMeshObstacle(导航网格障碍物):
- 该组件用于表示场景中的动态障碍物。当一个对象附加了
NavMeshObstacle
时,它会影响NavMeshAgent
的导航路径。 - 可以设置为
Carve
模式,这会在 NavMesh 上动态地修改 NavMesh,使代理能够绕开障碍物。
- 该组件用于表示场景中的动态障碍物。当一个对象附加了
二、导航行为和逻辑
- 路径规划:
NavMeshAgent
会自动根据 NavMesh 为代理规划从当前位置到目标位置的最短路径。它会考虑障碍物和可行走区域。- 可以使用
agent.remainingDistance
来检查代理离目标的剩余距离,使用agent.pathStatus
来查看路径的状态,如是否完成、正在计算或被阻塞。
- 避障:
- Unity 的导航系统会自动处理代理之间和代理与障碍物之间的避障。通过设置
NavMeshAgent
的属性,如Radius
和Avoidance Priority
,可以调整避障行为。 - 代理之间会根据彼此的
Avoidance Priority
进行避障,较低优先级的代理会主动避让较高优先级的代理。
- Unity 的导航系统会自动处理代理之间和代理与障碍物之间的避障。通过设置
- 动态导航:
- 当场景中的障碍物或目标位置发生变化时,
NavMeshAgent
会自动重新计算路径。 - 例如,如果要在游戏运行时改变目标位置,可以调用
agent.SetDestination(newDestination);
,其中newDestination
是一个Vector3
类型的新位置。
- 当场景中的障碍物或目标位置发生变化时,
开始实践
window→package manager 选择 Unity Registry 然后搜索 AI Navigation
window→ai→navigation(obsolete) ,这里是因为我所使用的Unity版本那个AI Navigation static 已经弃用了,我更改了一种使用方式。
选择Environment,然后为点击Inspector中的Static,接着将Environment的对象及其子对象都设置为Navigation Static.
点击Bake→bake
为Enemy添加NavMeshAgent,让敌人可以在NavMesh上面行走。
绘制几个路径点,用于敌人的自动巡逻。
引用巡逻点,编辑EnemyBehavior脚本
// 巡逻点的transformpublic Transform PatrolRoute;// 四个巡逻点的transform集合public List<Transform> Locations;void Start(){// 脚本运行时,初始化巡逻路径InitializePatrolRoute();}void InitializePatrolRoute(){foreach (Transform t in PatrolRoute){Locations.Add(t);}}
让Enemy跟着巡逻点动起来,在此编辑脚本
// ...
// 默认第一个索引为0,即先走第一个巡逻点
private int _locationIndex = 0;// NavMeshAgent的引用
private NavMeshAgent _agent;void Start()
{// 获取Enemy对象上的NavMeshAgent组件的引用_agent = GetComponent<NavMeshAgent>(); // 脚本运行时,初始化巡逻路径InitializePatrolRoute(); MoveToNextPatrolLocation();
}// 移动到下一个巡逻点
void MoveToNextPatrolLocation()
{_agent.destination = Locations[_locationIndex].position;
}
//....
现在只会移动到第一个巡逻点,然后我们的目的是,在每个巡逻点,循环往复的进行移动,这个时候就需要在Update()中搞点事情了。
void Update()
{// 检测当前对象与目标位置距离if(_agent.remainingDistance < 0.2f && !_agent.pathPending){MoveToNextPatrolLocation();}
}// 移动到下一个巡逻点void MoveToNextPatrolLocation(){if(Locations.Count == 0) return;_agent.destination = Locations[_locationIndex].position;// 索引循环往复_locationIndex = (_locationIndex + 1) % Locations.Count; }
🎃 敌人游戏机制
敌人按照巡逻路线进行巡逻,当与玩家碰撞后,减少玩家生命值,然后敌人回到初始位置,玩家也可以攻击敌人,减少其生命值。
追踪玩家
当玩家进入敌人警戒范围时,敌人会直接奔向玩家。
// 玩家的Transform引用public Transform Player;void Start(){// ...// 获取Player对象的引用Player = GameObject.Find("Player").transform;}// ...// 碰撞触发器void OnTriggerEnter(Collider other){if(other.name == "Player"){// 玩家进入到警戒范围后,敌人奔向玩家_agent.destination = Player.position;Debug.Log("玩家进入警戒范围");} }
攻击玩家
攻击玩家的逻辑很简单,当玩家与敌人发生碰撞时,玩家减少生命值,并且在GUI上显示
修改玩家的Playerbehavior脚本(敌人脚本也可以,因为碰撞是相互的)
// gameManager的引用,因为HP,收集道具数量都在该处存放
private GameBehavior _gameManager;void Start(){// 将当前player的刚体组件获取并设置_rb = GetComponent<Rigidbody>();// 获取当前角色的胶囊碰撞体_col = GetComponent<CapsuleCollider>();_gameManager = GameObject.Find("Game_Manager").GetComponent<GameBehavior>();}// 发生碰撞时void OnCollisionEnter(Collision collision){// 如果与敌人碰撞则HP-1if (collision.gameObject.name == "Enemy"){_gameManager.HP -= 1;}}
这里的话需要注意一个问题,就是敌人身上的碰撞体为碰撞触发器,勾选了Is Trigger,然后直接通过Player的OnCollisionEnter()并不会触发,需要给敌人再加入一个碰撞体就可以了。
子弹碰撞
为Player添加反击手段,逻辑就是敌人有三滴血,当子弹射击三次并且击中敌人后,敌人自动销毁。
编辑敌人Enemy的游戏脚本
// 敌人的HP=3
private int _lives = 3;
public int EnemyLives
{get { return _lives; }set{_lives = value;if (_lives <= 0){Destroy(this.gameObject);Debug.Log("敌人死亡");}}
}void OnCollisionEnter(Collision collision)
{// 当子弹碰撞到敌人时if(collision.gameObject.name == "Bullet(Clone)"){EnemyLives -= 1;Debug.Log("遭受子弹射击");}
}
完善游戏失败条件
逻辑是,生命值为0时,游戏暂停,出现一个按钮说:你输了。
先绘制一个Button按钮,和之前的一样,默认禁用即可,当生命值为0时,在脚本内调用。
编辑GameManager的脚本
public Button LossButton;
private int _playerHp = 10;
public int HP
{get { return _playerHp; }set{//...if (_playerHp <= 0){ProgressText.text = "You want another life with that?";LossButton.gameObject.SetActive(true);Time.timeScale = 0f;}else{ProgressText.text = "Ouch... that's got hurt.";}Debug.LogFormat("HP:{0}", _playerHp);}
}
🤗 总结归纳
本文主要介绍了在 Unity 中实现 AI 导航以及构建敌人游戏机制的方法。包括导航系统的基本组件、导航行为和逻辑,以及敌人的巡逻、追踪玩家、攻击玩家、被子弹击中和完善游戏失败条件等功能。
重要亮点
- 导航系统基本组件:Unity 中 AI 导航的基础是 NavMesh,它将场景中的可行走表面进行三角剖分形成网格。NavMeshAgent 是附加在游戏对象上用于在 NavMesh 上移动的组件,NavMeshObstacle 用于表示动态障碍物。
- 导航行为和逻辑:NavMeshAgent 能自动规划从当前位置到目标位置的最短路径,处理避障和动态导航。例如,当场景中的障碍物或目标位置变化时,会自动重新计算路径。
- 敌人巡逻机制:通过为敌人添加 NavMeshAgent,设置巡逻点,编写脚本实现敌人在巡逻点之间循环往复移动。
- 追踪玩家:当玩家进入敌人警戒范围时,敌人会奔向玩家。通过在敌人脚本中检测玩家进入碰撞触发器,设置敌人的目标位置为玩家位置。
- 攻击玩家:当玩家与敌人发生碰撞时,玩家减少生命值。在玩家脚本和敌人脚本中分别处理碰撞事件。
- 完善游戏失败条件:当玩家生命值为 0 时,游戏暂停,出现 “你输了” 按钮。在游戏管理器脚本中根据玩家生命值控制按钮的显示和游戏时间的暂停。
相关文章:

Unity自学之旅05
Unity自学之旅05 Unity学习之旅⑤📝 AI基础与敌人行为🥊 AI导航理论知识(基础)开始实践 🎃 敌人游戏机制追踪玩家攻击玩家子弹碰撞完善游戏失败条件 🤗 总结归纳 Unity学习之旅⑤ 📝 AI基础与敌…...

linux中关闭服务的开机自启动
引言 systemctl 是 Linux 系统中用于管理 systemd 服务的命令行工具。它可以用来启动、停止、重启服务,管理服务的开机自启动,以及查看服务的状态等。 什么是 systemd? systemd 是现代 Linux 发行版中默认的 初始化系统(init sys…...

Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )
一、文件处理 1.1、文件操作的重要性和应用场景 1.1.1、重要性 数据持久化: 文件是存储数据的一种非常基本且重要的方式。通过文件,我们可 以将程序运行时产生的数据永久保存下来,以便将来使用。 跨平台兼容性: 文件是一种通用…...

ubuntu黑屏问题解决
重启Ubuntu后,系统自动进入tty1,无法进入桌面。想到前几天安装了一些主题之类的,然后今天才重启,可能是这些主题造成冲突或者问题了把。 这里直接重新安装ubuntu-desktop解决: 更新源: sudo apt-get upd…...

Java如何实现反转义
Java如何实现反转义 前提 最近做的一个需求,是热搜词增加换一批的功能。功能做完自测后,交给了测试伙伴,但是测试第二天后就提了一个bug,出现了未知词 levis。第一眼看着像公司售卖的一个品牌-李维斯。然后再扒前人写的代码&…...

动态规划(路径问题)
62. 不同路径 62. 不同路径 - 力扣(LeetCode) 动态规划思想第一步:描述状态~ dp[i][j]:表示走到i,j位置时,一共有多少种方法~ 动态规划思想第二步:状态转移方程~ 动态规划思想第三步…...

python http调用视觉模型moondream
目录 一、什么是moondream 二、资源地址 三、封装了http进行接口请求 四、代码解析 解释 可能的改进 一、什么是moondream Moondream 是一个针对视觉生成任务的深度学习模型,专注于图像理解和生成,包括图像标注(captioning)、问题回答(Visual Question Answering,…...

Spark Streaming编程基础
文章目录 1. 流式词频统计1.1 Spark Streaming编程步骤1.2 流式词频统计项目1.2.1 创建项目1.2.2 添加项目依赖1.2.3 修改源目录1.2.4 添加scala-sdk库1.2.5 创建日志属性文件 1.3 创建词频统计对象1.4 利用nc发送数据1.5 启动应用,查看结果 2. 编程模型的基本概念3…...

深入 Flutter 和 Compose 的 PlatformView 实现对比,它们是如何接入平台控件
在上一篇《深入 Flutter 和 Compose 在 UI 渲染刷新时 Diff 实现对比》发布之后,收到了大佬的“催稿”,想了解下 Flutter 和 Compose 在 PlatformView 实现上的对比,恰好过去写过不少 Flutter 上对于 PlatformView 的实现,这次恰好…...

C# OpenCV机器视觉:红外体温检测
在一个骄阳似火的夏日,全球却被一场突如其来的疫情阴霾笼罩。阿强所在的小镇,平日里熙熙攘攘的街道变得冷冷清清,人们戴着口罩,行色匆匆,眼神中满是对病毒的恐惧。阿强作为镇上小有名气的科技达人,看着这一…...

FCA-FineDataLink认证
FCA-FineDataLink证书 Part.1:判断题 (总分:18分 得分:16) 第1题 判断题 数据同步只支持写入到已存在表,不支持自动建表(得分:2分 满分:2分) 正确答案:B 你的答案&…...

第19篇:python高级编程进阶:使用Flask进行Web开发
第19篇:python高级编程进阶:使用Flask进行Web开发 内容简介 在第18篇文章中,我们介绍了Web开发的基础知识,并使用Flask框架构建了一个简单的Web应用。本篇文章将深入探讨Flask的高级功能,涵盖模板引擎(Ji…...

js截取video视频某一帧为图片
1.代码如下 <template><div class"box"><div class"video-box"><video controls ref"videoRef" preload"true"src"https://qt-minio.ictshop.com.cn:9000/resource-management/2025/01/08/7b96ac9d957c45a…...

[云讷科技]Kerloud Falcon四旋翼飞车虚拟仿真空间发布
虚拟仿真环境作为一个独立的专有软件包提供给我们的客户,用于帮助用户在实际测试之前验证自身的代码,并通过在仿真引擎中添加新的场景来探索新的飞行驾驶功能。 环境要求 由于环境依赖关系,虚拟仿真只能运行在装有Ubuntu 18.04的Intel-64位…...

Jetson nano 安装 PCL 指南
本指南帮助 ARM64 架构的 Jetson Nano 安装 PCL(点云库)。 安装步骤 第一步:安装依赖 在终端中运行以下命令,安装 PCL 所需的依赖: sudo apt-get update sudo apt-get install git build-essential linux-libc-dev s…...

go-zero框架基本配置和错误码封装
文章目录 加载配置信息配置 env加载.env文件配置servicecontext 查询数据生成model文件执行查询操作 错误码封装配置拦截器错误码封装 接上一篇:《go-zero框架快速入门》 加载配置信息 配置 env 在项目根目录下新增 .env 文件,可以配置当前读取哪个环…...

Android中Service在新进程中的启动流程2
目录 1、Service在客户端的启动入口 2、Service启动在AMS的处理 3、Service在新进程中的启动 4、Service与AMS的关系再续 上一篇文章中我们了解了Service在新进程中启动的大致流程,同时认识了与客户端进程交互的接口IApplicationThread以及与AMS交互的接口IActi…...

论文速读|Matrix-SSL:Matrix Information Theory for Self-Supervised Learning.ICML24
论文地址:Matrix Information Theory for Self-Supervised Learning 代码地址:https://github.com/yifanzhang-pro/matrix-ssl bib引用: article{zhang2023matrix,title{Matrix Information Theory for Self-Supervised Learning},author{Zh…...

ubunut22.04安装docker(基于阿里云 Docker 镜像源安装 Docker)
安装 更新包管理器: sudo apt update 安装 Docker 的依赖包 sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release添加阿里云 Docker 镜像源 GPG 密钥: curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gp…...

k8s namespace绑定节点
k8s namespace绑定节点 1. apiserver 启用准入控制 PodNodeSelector2. namespace 添加注解 scheduler.alpha.kubernetes.io/node-selector3. label node 1. apiserver 启用准入控制 PodNodeSelector vim /etc/kubernetes/manifests/kube-apiserver.yaml spec:containers:- co…...

【ElementPlus】在Vue3中实现表格组件封装
预览 搜索筛选组件 <template><div><el-formref"formView":model"formData"label-width"auto"label-position"right":label-col-style"{ min-width: 100px }":inline"true"><el-form-item …...

cursor重构谷粒商城04——vagrant技术快速部署虚拟机
前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城…...

26、正则表达式
目录 一. 匹配字符 .:匹配除换行符外的任意单个字符。 二. 位置锚点 ^:匹配输入字符串的开始位置。 $:匹配输入字符串的结束位置。 \b:匹配单词边界。 \B:匹配非单词边界。 三. 重复限定符 *:匹配…...

SpringBoot使用MockMVC通过http请求controller控制器调用测试
说明 在Spring Boot中编写测试控制器调用是一个常见的需求,通常使用Spring的测试框架来完成。Spring Boot提供了多种方式来测试控制器,包括使用MockMvc进行模拟HTTP请求和响应的测试。 基本示例 1. 创建Spring Boot项目 首先,确保你已经创建了一个Spring Boot项目。如果…...

【Unity3D】Unity混淆工具Obfuscator使用
目录 一、导入工具 二、各种混淆形式介绍 2.1 程序集混淆 2.2 命名空间混淆 2.3 类混淆 2.4 函数混淆 2.5 参数混淆 2.6 字段混淆 2.7 属性混淆 2.8 事件混淆 三、安全混淆 四、兼容性处理 4.1 动画方法兼容 4.2 GUI方法兼容 4.3 协程方法兼容 五、选项 5.1 调…...

C语言语法基础学习—动态分配空间(new和malloc的用法及区别)
前言 在 C 语言中,动态内存分配主要是通过 malloc() 和 free() 函数来完成的。而在 C 中是使用new和delete关键字,来动态分配内存。 虽然 C 语言没有 new,但 malloc() 和 new 在内存分配上的作用是相似的。下面我们详细解释 malloc() 和 ne…...

QT:控件属性及常用控件(3)-----输入类控件(正则表达式)
输入类控件既可以进行显示,也能让用户输入一些内容! 文章目录 1.Line Edit1.1 用户输入个人信息1.2 基于正则表达式的文本限制1.3 验证两次输入的密码是否一致1.4 让输入的密码可以被查看 2.Text Edit2.1 输入和显示同步2.1 其他信号出发情况 3.ComboBox…...

Hive SQL 执行计划解析
Hive SQL 执行计划解析 一、 explain用法 1. SQL 查询 EXPLAIN SELECT SUM(view_dsp) AS view_sum FROM ads.table_a WHERE p_day 2025-01-06;2. 执行计划 STAGE DEPENDENCIES:Stage-1 is a root stageStage-0 depends on stages: Stage-1STAGE PLANS:Stage: Stage-1Map …...

热更新杂乱记
热更新主要有一个文件的MD5值的比对过程,期间遇到2个问题,解决起来花费了一点时间 1. png 和 plist 生成zip的时候再生成MD5值会发生变动。 这个问题解决起来有2种方案: (1).第一个方案是将 png和plist的文件时间改…...

博客搭建 — GitHub Pages 部署
关于 GitHub Pages GitHub Pages 是一项静态站点托管服务,它直接从 GitHub 上的仓库获取 HTML、CSS 和 JavaScript 文件,通过构建过程运行文件,然后发布网站。 本文最终效果是搭建出一个域名为 https://<user>.github.io 的网站 创建…...