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变量添加浮点数类型,因为现在没有初始值,它无法自动推断出类型
  • 更新函数里面根据最大值和最小值进行随机生成一个速度变量
相关推荐
Century_Dragon几秒前
把一辆智能汽车“搬“进教室—智能网联汽车自动驾驶虚拟教学实训
学习
兔头?3 分钟前
JVM学习文档
jvm·学习
hkNaruto4 分钟前
【AI】深度学习、强化学习、深度强化学习基础概念笔记
人工智能·笔记·深度学习
秦禹辰25 分钟前
ClipSketch AI把视频改造成图文漫画:选关键帧、生成手绘分镜、融合IP形象并自动写小红书文案
人工智能·tcp/ip·音视频
SmalBox39 分钟前
07-01-打包系统-资源分组策略
unity3d·游戏开发
无心水1 小时前
15、云原生架构设计理论与实践 核心考点与学习笔记
笔记·学习·云原生·架构师·软考·系统架构设计师·软考系统架构设计师
动词ing1 小时前
【学习笔记】51单片机 独立按键控制LED显示二进制
笔记·学习·51单片机
叼烟扛炮1 小时前
Linux 学习笔记(三十九):网络基石——TCP/IP 模型与 UDP 实战
linux·运维·网络·笔记·学习·tcp/ip
闲云野鹤在人间1 小时前
头秃修炼手册:StorageClass+StatefulSet+ETCD 全套渡劫笔记
linux·数据库·笔记·云原生·kubernetes·etcd
派大猩猩_2 小时前
选题散在 20 篇笔记里?Nutstore Sync在 Obsidian 里创建选题小工具,创作动线短一半
笔记·obsidian·obsidian插件·obsidian ai