当前位置: 首页 > article >正文

Unity敌人逻辑笔记

写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 callbacks
    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex){
        if(myAI.DetectEnemy()){
            animator.SetBool(MyNPCAI.foundEnemyPara,true);
        }
    }
}

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

效果演示 

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


http://www.kler.cn/a/525471.html

相关文章:

  • Kafka 消费端反复 Rebalance: `Attempt to heartbeat failed since group is rebalancing`
  • 【C语言】内存函数
  • [论文总结] 深度学习在农业领域应用论文笔记14
  • 小白爬虫冒险之反“反爬”:无限debugger、禁用开发者工具、干扰控制台...(持续更新)
  • 快速提升网站收录:内容创作的艺术
  • ResNeSt: Split-Attention Networks 参考论文
  • 推动知识共享的在线知识库实施与优化指南
  • java实现mysql数据库备份还原定时删除过期备份文件
  • JavaScript图像处理,JavaScript实现高斯滤波图像处理算法
  • http://noi.openjudge.cn/——4.2算法之数论——2419:Coins
  • 【面试】【前端】SSR与SPA的优缺点
  • doris:Bitmap
  • 3.4 Go函数作用域(标识符)
  • 【C++】内联函数inline、关键字auto与新式for
  • 数字化转型-工具变量(2024.1更新)-社科数据
  • C++并发编程指南02
  • 动手学图神经网络(8):在消息传递中定制聚合操作
  • 什么是 AI 代理?
  • redis中n是什么含义?
  • 从春晚《秧BOT》来看人形机器人与四足机器人的区别
  • IPhone13 Pro Max设备详情
  • 寒假学web--day06
  • arkui-x跨平台与android java联合开发
  • 解读隐私保护工具 Fluidkey:如何畅游链上世界而不暴露地址?
  • 微服务学习-服务调用组件 OpenFeign 实战
  • 四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)