Unity敌人逻辑笔记

news/2025/1/30 22:38:25/

写ai逻辑基本上都需要状态机。因为懒得手搓状态机,所以选择直接用动画状态机当逻辑状态机用。

架构设计

因为敌人的根节点已经有一个animator控制动画,只能增加一个子节点AI,给它加一个animator指向逻辑“动画”状态机。还有一个脚本,用来放一些检测函数和动画事件函数。

状态机图

敌人的行为描述:默认处在Safe状态,未发现敌人一段时间后进入Patrol状态,朝周围随机位置移动,一段时间且未发现敌人后停止。如果设置有目的地则进入Moving,离目的地在一定距离内且未发现敌人进入Safe。在Safe、Patrol、Moving发现了敌人都把foundEnemy和alert设置True,alert为Trur则进入Alert,foundEnemy为True则进入Attacking。Attacking开枪几秒,停歇几秒。如果此时检测敌人返回false,则foundEnemy设置为false,进入Chasing,根据之前记录的目标最后出现的位置移动过去,到那里后未发现目标则进入Alert,未发现敌人一段时间后进入Safe。

所有状态都不停执行检测敌人的方法。

动画剪辑设置

动画剪辑添加一个无关紧要的属性(如Scale)来卡时间。重要的是在特定的时间执行动画事件。如在Safe一段时间后开始巡逻:

public void StartPatrolling(){enemyController.SetBool(patrolling,true);}

 攻击状态开枪几秒,停歇几秒,然后检查是否该换弹:

 

 

状态机行为脚本

在状态机行为脚本里满足某些条件时执行animator.SetXXX()改变动画参数,动画参数改变又引起状态转换,执行新的状态机行为脚本,可以达到状态机“自驱动”的效果。

如在Alert状态的OnStateUpdate()里不停检测敌人,检测到时设置foundEnemy进入攻击状态。

public class EnemyAlert : StateMachineBehaviour
{Character1 myCharacter;MyNPCAI myAI;override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex){myCharacter=animator.transform.parent.GetComponent<Character1>();myCharacter.PutAwayGun();myAI=animator.GetComponent<MyNPCAI>();myCharacter.PlayRandomClip(myAI.findAudio);myCharacter.UseRifle();myAI.StopLookingAround();}// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacksoverride public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex){if(myAI.DetectEnemy()){animator.SetBool(MyNPCAI.foundEnemyPara,true);}}
}

但是每个状态机行为脚本进入时都要获取一遍组件。这很恶心。 

效果演示 

Unity简单敌人逻辑演示:巡逻、发现、攻击、追击_演示


http://www.ppmy.cn/news/1567992.html

相关文章

GRAPHARG——学习

20250106 项目git地址&#xff1a;https://github.com/microsoft/graphrag.git 版本&#xff1a;1.2.0 ### This config file contains required core defaults that must be set, along with a handful of common optional settings. ### For a full list of available setti…

汽车表面划痕刮伤检测数据集VOC+YOLO格式1221张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1221 标注数量(xml文件个数)&#xff1a;1221 标注数量(txt文件个数)&#xff1a;1221 …

【AI】【本地部署】OpenWebUI的升级并移植旧有用户信息

【背景】 OpenWebUI的版本升级频率很高&#xff0c;并会修改旧版本的Bug&#xff0c;不过对于已经在使用的系统&#xff0c;升级后现有用户信息都会丢失&#xff0c;于是研究如何在升级后将现有的用户信息移植到升级后版本。 【准备工作】 OpenWebUI的升级步骤在Docker中有现…

flutter入门系列教程<三>:tabbar的高度自适用,支持无限滚动

背景 在之前的文章中&#xff0c;简介了tabbar组件的使用&#xff0c;它通常用于顶部放置tabbar标签页头&#xff0c;内容全部都是TabbarView的全部内容&#xff0c;且内容通常是占满屏幕的&#xff08;尽可能大&#xff09;&#xff0c;如下&#xff1a; 但是有时候我们需要…

如何在Windows系统上安装和配置Node.js及Node版本管理器(nvm)

Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;广泛用于开发高性能的网络应用。它使得JavaScript不仅能在浏览器端运行&#xff0c;还能在服务器端执行。对于开发者来说&#xff0c;Node.js是现代Web应用的核心之一。安装和配置Node.js后&#xff0c;很多开…

P4681 [THUSC 2015] 平方运算 Solution

Description 给定序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1​,a2​,⋯,an​) 和常数 p p p &#xff0c;有 m m m 个操作&#xff0c;分以下两种&#xff1a; modify ⁡ ( l , r ) \operatorname{modify}(l,r) modify(l,r)&#xff1a;对每个 i ∈ [ …

26.useScript

在 Web 应用开发中&#xff0c;动态加载外部脚本是一个常见需求&#xff0c;特别是在需要集成第三方库或服务时。然而&#xff0c;在 React 应用中管理脚本加载可能会变得复杂。useScript 钩子提供了一种优雅的方式来处理外部脚本的加载、错误处理和清理&#xff0c;使得在 Rea…

web前端三大主流框架对比,Angular和React和Vue的区别

为什么说学会多种框架是很有好处的呢?其实从本质上来说&#xff0c;框架使编程变得更加有趣&#xff0c;并且框架使初学者更容易出成果&#xff0c;软件架构有就显得极为重要&#xff0c;那么你知道web前端三大主流框架对比&#xff0c;Angular和React和Vue之间有什么区别呢?…