Skip to content
Development
Skill

/godot-navigation-system

NavigationAgent2D使用、AStarGrid2D算法、自定义A*实现、流式寻路及性能优化。用于2D/3D导航系统、动态障碍物避让、游戏AI导航等场景。

BOOST
From plugin
alphaagent
10419 skills
Install
$ npx -y skills add 925236118/AlphaAgent --skill godot-navigation-system --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/godot-navigation-system

Context preview

The summary Claude sees to decide when to auto-load this skill.

NavigationAgent2D使用、AStarGrid2D算法、自定义A*实现、流式寻路及性能优化。用于2D/3D导航系统、动态障碍物避让、游戏AI导航等场景。

SKILL.md

godot-navigation-system.SKILL.md
name: godot-navigation-system
description: NavigationAgent2D使用、AStarGrid2D算法、自定义A*实现、流式寻路及性能优化。用于2D/3D导航系统、动态障碍物避让、游戏AI导航等场景。

Godot 导航与寻路系统

Godot 4 导航系统完整指南,涵盖 NavigationAgent2D、AStarGrid2D、自定义 A* 算法、流场寻路及性能优化策略。

何时使用此技能

  • 需要 NavigationServer2D/3D 导航系统
  • 实现游戏AI寻路导航
  • 需要动态障碍物和NavLink连接
  • 优化大量单位的寻路性能

1. NavigationAgent2D 使用

NavigationAgent2D 是 Godot 4 推荐的 2D 导航解决方案,封装了 NavigationServer 的复杂操作。

基础设置

# navigation_agent_2d.gd
class_name NavigationAgent2D
extends NavigationAgent2D

signal navigation_finished
signal path_changed
signal target_reached

@export var actor: CharacterBody2D
@export var move_speed: float = 200.0

var _target_position: Vector2 = Vector2.ZERO

func _ready() -> void:
    # 设置代理半径(障碍物避让)
    agent_height = 0
    agent_max_speed = move_speed

    # 连接信号
    navigation_finished.connect(_on_navigation_finished)
    path_changed.connect(_on_path_changed)
    target_reached.connect(_on_target_reached)

    # 等待NavigationServer同步
    await get_tree().physics_frame
    await get_tree().physics_frame

func _physics_process(delta: float) -> void:
    if actor and _target_position != Vector2.ZERO:
        if is_navigation_finished():
            return

        var next_pos := get_next_path_position()
        var current_pos := actor.global_position
        var new_velocity := (next_pos - current_pos).normalized() * move_speed

        actor.velocity = new_velocity
        actor.move_and_slide()

func set_target(world_position: Vector2) -> void:
    _target_position = world_position
    target_position = world_position

func _on_navigation_finished() -> void:
    navigation_finished.emit()

func _on_path_changed() -> void:
    path_changed.emit()

func _on_target_reached() -> void:
    target_reached.emit()

NavigationRegion2D 导航区域

# navigation_region.gd
class_name NavigationRegion
extends NavigationRegion2D

@export var tile_map: TileMap
@export var bake_on_ready: bool = true

func _ready() -> void:
    if bake_on_ready:
        await get_tree().physics_frame
        bake_navigation_polygon()

# 从 TileMap 几何数据生成导航多边形
func bake_from_tilemap() -> void:
    var polygon := NavigationPolygon.new()
    var outline: Array[Vector2] = []

    var used_rect := tile_map.get_used_rect()

    for x in range(used_rect.size.x):
        for y in range(used_rect.size.y):
            var cell := Vector2i(used_rect.position.x + x, used_rect.position.y + y)
            var tile_data := tile_map.get_cell_tile_data(0, cell)

            if tile_data and tile_data.get_custom_data("obstacle"):
                # 障碍物格子不加入导航
                continue

            var world_pos := tile_map.map_to_local(cell)
            outline.append(world_pos)

    if not outline.is_empty():
        polygon.add_outline(outline)
        polygon.make_polygons_from_outlines()

    navigation_polygon = polygon
    bake_navigation_polygon()

动态障碍物

# dynamic_obstacle.gd
class_name DynamicObstacle
extends Area2D

@export var radius: float = 32.0
@export var navigation_region: NavigationRegion

var _last_position: Vector2

func _ready() -> void:
    area_entered.connect(_on_area_entered)
    area_exited.connect(_on_area_exited)

func _physics_process(_delta: float) -> void:
    if global_position != _last_position:
        _last_position = global_position
        _update_navigation()

func _update_navigation() -> void:
    # 简单实现:移动时重新烘焙导航网格
    # 生产环境建议使用 NavigationMesh::update()
    if navigation_region:
        navigation_region.bake_navigation_polygon()

func _on_area_entered(area: Area2D) -> void:
    # 障碍物进入逻辑
    pass

func _on_area_exited(area: Area2D) -> void:
    # 障碍物离开逻辑
    pass

2. AStarGrid2D 算法实现

AStarGrid2D 是 Godot 4 内置的高效网格寻路组件,适合规则网格的快速 A* 搜索。

基础 AStarGrid2D

# astar_grid_2d.gd
class_name AStarGrid2D
extends Node

@export var tile_map: TileMap
@export var obstacles_layer: int = 0

var _grid: AStarGrid2D

func _ready() -> void:
    _setup_grid()

func _setup_grid() -> void:
    var region := tile_map.get_used_rect()

    _grid = AStarGrid2D.new()
    _grid.size = region.size
    _grid.offset = tile_map.tile_set.tile_size / 2
    _grid.cell_size = tile_map.tile_set.tile_size
    _grid.center = false
    _grid.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER

    _grid.update()

    # 标记障碍物
    for cell in tile_map.get_used_cells(obstacles_layer):
        var tile_data := tile_map.get_cell_tile_data(obstacles_layer, cell)
        if tile_data and tile_data.get_custom_data("obstacle"):
            _grid.set_point_solid(cell - region.position)

func find_path(start: Vector2i, end: Vector2i) -> PackedVector2Array:
    var region := tile_map.get_used_rect()
    var local_start := start - region.position
    var local_end := end - region.position

    if not _grid.is_point_inside(local_start) or not _grid.is_point_inside(local_end):
        return PackedVector2Array()

    if _grid.is_point_solid(local_start) or _grid.is_point_solid(local_end):
        return PackedVector2Array()

    var path := _grid.get_point_path(local_start, local_end)

    # 转换回世界坐标
    var world_path := PackedVector2Array()
    for point in path:
        world_path.append(tile_map.map_to_local(point + region.position))

    return world_path

func is_walkable(cell: Vector2i) -> bool:
    var region := tile_map.get_used_rect()
    var local_cell := cell - region.position

    if not _grid.is_point_inside(local_cell):
        return false

    return not _grid.is_point_solid(local_cell)

func set_obstacle(cell: Vector2i, obstacle: bool) -> void:
    var region := tile_map.get_used_rect()
    var local_cell := cell - region.position

    if obstacle:
        _grid.set_point_solid(local_cell)
    else:
        _grid.clear_point(local_cell)

带权重的 AStarGrid2D

# weighted_astar_grid.gd
class_name WeightedAStarGrid
extends AStarGrid2D

var _cell_weights: Dictionary = {}

func _ready() -> void:
    _setup_grid()

func _setup_grid()
Read more
Ships withalphaagent

为Godot引擎编辑器开发的Ai Agent插件

Get the whole plugin

Other skills on alphaagent.

godot-tscn-format
Skill

godot-tscn-format

Godot 4.x .tscn 场景文件纯文本格式规范与 AI 操作指南 — 文件结构、资源引用、 Transform 变换、属性值格式、信号连接,以及 AI 直接读写 .tscn 文件的操作方法。