godot2D游戏教程系列二(25)

前言:


目标

使用 NavigationAgent2D 避让功能

  • 敌人之间保持距离
  • 不互相重叠
  • 随机移动速度
  • 修复速度叠加问题

一、开启避让功能

选中 Enemy 场景里的 ​​NavigationAgent2D​​:

在 Inspector 中:

  • ✅ 启用 Avoidance
  • Radius = 30 → 扩大检测碰撞范围
  • Max Speed = 20 → 避让时的移动速度

作用:

当敌人靠近时自动计算"安全速度"。


二、连接避让信号

使用信号:

复制代码
velocity_computed(safe_velocity)

双击该信号 → 添加到 移动状态脚本


三、在信号函数中处理避让

复制代码
func _on_navigation_agent_2d_velocity_computed(safe_velocity: Vector2):

    if state_machine.current_state != self:
        return

    character.velocity = safe_velocity

⚠ 为什么不能叠加?

错误写法:

复制代码
character.velocity += safe_velocity * delta

问题:

  • 每帧累加
  • 速度会不断增加
  • 敌人会突然弹开

正确做法:

  • 直接使用 safe_velocity
  • 或者使用 lerp 平滑过渡

四、给敌人随机移动速度

1️⃣ 定义常量

复制代码
const SPEED_MIN = 60
const SPEED_MAX = 120

2️⃣ 声明 speed 类型

复制代码
var speed: float

⚠ 必须写类型,因为没有默认值。


3️⃣ 在 enter() 中随机生成

复制代码
func enter():
    speed = randf_range(SPEED_MIN, SPEED_MAX)
    timer.start()

说明:

  • 每个敌人进入移动状态时
  • 生成不同速度
  • 行为更自然

五、完整移动逻辑结构

1️⃣ Timer 更新目标位置

每 0.5 秒更新:

复制代码
nav_agent.target_position = player.global_position

2️⃣ physics_update 里
复制代码
var next_path_position = nav_agent.get_next_path_position()
direction = (next_path_position - character.global_position).normalized()
nav_agent.velocity = direction * speed

注意:

  • 现在使用 nav_agent.velocity
  • 不直接改 character.velocity

3️⃣ velocity_computed 信号中
复制代码
character.velocity = safe_velocity
character.move_and_slide()

最终效果

✔ 敌人之间自动分开

✔ 不会重叠

✔ 不会速度叠加爆炸

✔ 每个敌人移动速度不同

✔ 行为更自然

现在敌人具备:

  • 寻路
  • 避让
  • 追击
  • 随机移动速度

已经是完整可扩展的基础 AI 系统。

实现过程:

  • 我们不希望敌人彼此重叠在一起,所以在这节课中,我们将利用导航系统的避让功能,让敌人之间保持一定的距离。
  • 敌人场景选中2d导航代理节点,到右边检查器启用避让功能,然后把半径属性增加到30,这样会让避让检测的碰撞体变得更大,另外把最大速度变为20,这个数值定义敌人在视图躲避其他敌人时的移动速度
  • 另外采用节点的velocity computed的信号,这就是躲避功能的工作原理,当这个敌人需要躲避其他敌人时,这个信号函数会被自动调用
  • 我们需要将这个安全速度与敌人的当前速度进行整合,这样它就能尝试避开其他敌人,让我们双击这个信号将其添加到敌人移动状态脚本中
  • 我们需要假设这个函数可能在敌人处于其他状态时被调用,所以首先检查父状态机的当前状态是否为这个移动状态,然后我们可以通过将安全速度加到角色速度上来更新角色的速度,移动过程是平滑的所以将其乘以增量时间
  • 然后我们会发现当玩家等待 当敌人在同一位置停留一会儿后玩家移动时它们会迅速分散开来,这是因为我们将安全速度叠加到敌人的速度上会随着时间累积。
  • 接下来让我们为每个敌人随机设置移动速度,我们声明一个名为SPEED_MAX,SPEED_MIN的常量,另外把之前的速度的变量注释掉
  • 我们还需要为speed变量添加浮点数类型,因为现在没有初始值,它无法自动推断出类型
  • 更新函数里面根据最大值和最小值进行随机生成一个速度变量
相关推荐
什仙32 分钟前
Maxwell:提取实体表面,用于扫掠。
笔记·学习·ansys·maxwell
小僧景贤33 分钟前
嵌入式C语言 第十一篇:成长路线|嵌入式C工程师完整进阶学习路径(从零到工程级落地|含周期+实战项目)
c语言·开发语言·学习
程序员老陆39 分钟前
音频为什么不编码成“声卡格式”(例如S16)?因为声卡只负责响,编码器只负责省
ffmpeg·音视频
调试到凌晨1 小时前
免费配音工具长文本处理能力实测:做长视频和有声书,谁更稳?
音视频
zyplayer-doc1 小时前
核心制度不该被随手修改:用zyplayer-doc锁定文档和全部子文档
大数据·数据库·人工智能·笔记·pdf·ocr
SmalBox2 小时前
【节点】[Keyword节点]原理解析与实际应用
unity3d·游戏开发·图形学
啄缘之间2 小时前
5.1 uvm‑component 的层级结构管理? new (name,parent) 参数
开发语言·笔记·学习·ic·uvm·sv
math_hongfan2 小时前
鸿蒙多模态AI交互高级:图文+语音+手势融合交互/多模态大模型端侧适配/跨模态检索高阶实战
人工智能·学习·华为·交互·语音识别·harmonyos·鸿蒙
旖旎夜光2 小时前
C++(类与对象)(下)
开发语言·c++·学习
江屿风3 小时前
【科普】【差集&交集概念落地云相册】流食般投喂
开发语言·c++·笔记·算法·云相册