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变量添加浮点数类型,因为现在没有初始值,它无法自动推断出类型
  • 更新函数里面根据最大值和最小值进行随机生成一个速度变量
相关推荐
甲维斯5 小时前
GLM5.2+ZCode复刻坦克大战,自测50万帧!
前端·ai编程·游戏开发
晓杰在写后端11 小时前
从0到1实现Balatro游戏后端(9):Blind奖励结算与金币系统实现
后端·游戏开发
SmalBox12 小时前
【节点】[SmoothWave节点]原理解析与实际应用
unity3d·游戏开发·图形学
甲维斯1 天前
用AI还原《坦克大战》并3D化升级!
前端·人工智能·游戏开发
甲维斯1 天前
坦克大战测试全翻车了!豆包,DeepSeek,Qwen,GPT,Claude
前端·人工智能·游戏开发
SmalBox1 天前
【节点】[RoundedRectangle节点]原理解析与实际应用
unity3d·游戏开发·图形学
LinXunFeng2 天前
Obsidian - 使用 Share Note 分享笔记并自部署
前端·笔记·github
_zhourui_h_2 天前
MyFramework:safe() 扩展函数的空集合设计
unity3d·游戏开发
SmalBox2 天前
【节点】[RoundedPolygon节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox4 天前
【节点】[Rectangle节点]原理解析与实际应用
unity3d·游戏开发·图形学