Godot群体行为模拟:AI智能体系统开发
2026-02-04 04:56:56作者:庞队千Virginia
还在为游戏中的NPC(Non-Player Character,非玩家角色)行为单一、缺乏真实感而烦恼吗?本文将带你深入探索Godot引擎中的群体行为模拟技术,通过NavigationAgent系统实现智能、自然的AI群体行为。
读完本文,你将掌握:
- NavigationAgent核心组件的工作原理
- 群体行为算法的实现原理
- 避障与路径规划的实战技巧
- 多智能体协同行为的开发方法
- 性能优化与调试的最佳实践
群体行为模拟技术概览
群体行为模拟(Swarm Behavior Simulation)是游戏AI开发中的重要领域,它模拟生物群体(如鸟群、鱼群、人群)的集体行为模式。在Godot中,我们主要通过NavigationAgent系统来实现这一功能。
核心组件架构
graph TB
A[NavigationServer] --> B[NavigationRegion]
A --> C[NavigationAgent]
A --> D[NavigationObstacle]
C --> E[路径规划 Pathfinding]
C --> F[避障机制 Avoidance]
C --> G[行为决策 Behavior]
E --> H[目标位置设置]
E --> I[路径查询]
E --> J[路径跟随]
F --> K[RVO碰撞避免]
F --> L[速度计算]
F --> M[优先级管理]
G --> N[状态机]
G --> O[群体规则]
G --> P[环境感知]
NavigationAgent核心功能解析
基础属性配置
NavigationAgent提供了丰富的配置选项来控制智能体的行为:
extends NavigationAgent3D
# 路径规划参数
@export var navigation_layers: int = 1 # 导航层掩码
@export var path_desired_distance: float = 1.0 # 路径点期望距离
@export var target_desired_distance: float = 1.0 # 目标期望距离
@export var path_max_distance: float = 5.0 # 路径最大偏离距离
# 避障参数
@export var avoidance_enabled: bool = true
@export var radius: float = 0.5 # 智能体半径
@export var height: float = 1.0 # 智能体高度
@export var max_neighbors: int = 10 # 最大邻居数量
@export var neighbor_distance: float = 50.0 # 邻居检测距离
@export var time_horizon_agents: float = 1.0 # 避障预测时间
@export var max_speed: float = 10.0 # 最大速度
路径规划工作流程
sequenceDiagram
participant A as 智能体
participant N as NavigationAgent
participant S as NavigationServer
participant M as 导航地图
A->>N: 设置target_position
N->>S: 请求路径查询
S->>M: 在导航网格上寻路
M-->>S: 返回路径点数组
S-->>N: 返回路径结果
N->>A: 触发路径更新信号
loop 每物理帧
A->>N: 调用get_next_path_position()
N->>A: 返回下一个路径点位置
A->>A: 向路径点移动
N->>S: 更新避障速度计算
S-->>N: 返回安全速度
N->>A: 触发velocity_computed信号
end
群体行为算法实现
基本群体规则实现
群体行为通常遵循三个基本规则:分离、对齐、聚集。以下是这些规则的GDScript实现:
class_name SwarmBehavior
# 分离规则:避免与邻居过于接近
static func separation(agent: Node3D, neighbors: Array, separation_distance: float) -> Vector3:
var steer := Vector3.ZERO
var count := 0
for neighbor in neighbors:
var dist = agent.global_position.distance_to(neighbor.global_position)
if dist > 0 and dist < separation_distance:
var diff = (agent.global_position - neighbor.global_position).normalized() / dist
steer += diff
count += 1
if count > 0:
steer /= count
return steer
# 对齐规则:与邻居保持相同方向
static func alignment(agent: Node3D, neighbors: Array) -> Vector3:
var steer := Vector3.ZERO
var count := 0
for neighbor in neighbors:
if neighbor.has_method("get_velocity"):
steer += neighbor.get_velocity()
count += 1
if count > 0:
steer /= count
steer = steer.normalized() * agent.max_speed if agent.has_method("get_max_speed") else steer.normalized()
return steer
# 聚集规则:向邻居中心移动
static func cohesion(agent: Node3D, neighbors: Array) -> Vector3:
var steer := Vector3.ZERO
var count := 0
for neighbor in neighbors:
steer += neighbor.global_position
count += 1
if count > 0:
steer /= count
return (steer - agent.global_position).normalized()
return Vector3.ZERO
完整群体智能体实现
extends CharacterBody3D
class_name SwarmAgent
@export_group("Movement Settings")
@export var max_speed: float = 5.0
@export var acceleration: float = 10.0
@export var rotation_speed: float = 5.0
@export_group("Swarm Behavior Weights")
@export var separation_weight: float = 1.5
@export var alignment_weight: float = 1.0
@export var cohesion_weight: float = 1.0
@export var target_weight: float = 2.0
@export_group("Detection Ranges")
@export var separation_distance: float = 2.0
@export var neighbor_distance: float = 8.0
@onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D
@onready var detection_area: Area3D = $DetectionArea
var current_velocity: Vector3 = Vector3.ZERO
var neighbors: Array = []
func _ready():
navigation_agent.velocity_computed.connect(_on_velocity_computed)
detection_area.body_entered.connect(_on_body_entered)
detection_area.body_exited.connect(_on_body_exited)
func _on_body_entered(body: Node):
if body is SwarmAgent and body != self:
if not neighbors.has(body):
neighbors.append(body)
func _on_body_exited(body: Node):
if body is SwarmAgent:
neighbors.erase(body)
func set_movement_target(target_position: Vector3):
navigation_agent.target_position = target_position
func _physics_process(delta):
if navigation_agent.is_navigation_finished():
return
# 获取邻居智能体
var nearby_agents = _get_nearby_agents()
# 计算群体行为力
var separation_force = SwarmBehavior.separation(self, nearby_agents, separation_distance) * separation_weight
var alignment_force = SwarmBehavior.alignment(self, nearby_agents) * alignment_weight
var cohesion_force = SwarmBehavior.cohesion(self, nearby_agents) * cohesion_weight
# 获取导航路径方向
var next_path_pos = navigation_agent.get_next_path_position()
var target_direction = (next_path_pos - global_position).normalized() * target_weight
# 合并所有力
var desired_velocity = (separation_force + alignment_force + cohesion_force + target_direction).normalized() * max_speed
# 设置速度给NavigationAgent进行避障计算
if navigation_agent.avoidance_enabled:
navigation_agent.velocity = desired_velocity
else:
_on_velocity_computed(desired_velocity)
func _on_velocity_computed(safe_velocity: Vector3):
# 平滑转向
var target_rotation = Transform3D().looking_at(safe_velocity.normalized(), Vector3.UP)
rotation = rotation.lerp(target_rotation.basis.get_euler(), rotation_speed * get_physics_process_delta_time())
# 应用速度
velocity = velocity.move_toward(safe_velocity, acceleration * get_physics_process_delta_time())
move_and_slide()
func _get_nearby_agents() -> Array:
var nearby: Array = []
for body in detection_area.get_overlapping_bodies():
if body is SwarmAgent and body != self:
var distance = global_position.distance_to(body.global_position)
if distance <= neighbor_distance:
nearby.append(body)
return nearby
高级群体行为模式
分层状态机实现
复杂的群体行为需要状态机来管理不同的行为模式:
enum AgentState {
IDLE, # 空闲状态
WANDERING, # 漫游状态
FOLLOWING, # 跟随状态
FLEEING, # 逃跑状态
FORMATION # 编队状态
}
extends SwarmAgent
var current_state: AgentState = AgentState.IDLE
var state_timer: float = 0.0
var wander_target: Vector3
func _physics_process(delta):
state_timer += delta
match current_state:
AgentState.IDLE:
_update_idle_state(delta)
AgentState.WANDERING:
_update_wandering_state(delta)
AgentState.FOLLOWING:
_update_following_state(delta)
AgentState.FLEEING:
_update_fleeing_state(delta)
AgentState.FORMATION:
_update_formation_state(delta)
func _update_idle_state(delta):
if state_timer > 2.0: # 空闲2秒后开始漫游
change_state(AgentState.WANDERING)
func _update_wandering_state(delta):
if state_timer > 5.0 or navigation_agent.is_navigation_finished():
# 设置新的漫游目标
wander_target = global_position + Vector3(
randf_range(-10, 10),
0,
randf_range(-10, 10)
)
set_movement_target(wander_target)
state_timer = 0.0
func change_state(new_state: AgentState):
current_state = new_state
state_timer = 0.0
match new_state:
AgentState.FLEEING:
max_speed = 8.0 # 逃跑时速度更快
_:
max_speed = 5.0 # 恢复正常速度
编队系统实现
class FormationSystem:
static func calculate_formation_position(leader: Node3D, index: int, formation_type: String) -> Vector3:
var offset: Vector3
match formation_type:
"V_SHAPE":
# V字形编队
var row = int(sqrt(index))
var col = index - row * row
offset = Vector3(col * 2.0, 0, -row * 2.0)
"LINE":
# 线性编队
offset = Vector3(index * 2.0, 0, 0)
"CIRCLE":
# 圆形编队
var angle = 2 * PI * index / 8 # 假设最多8个成员
var radius = 4.0
offset = Vector3(cos(angle) * radius, 0, sin(angle) * radius)
_:
offset = Vector3.ZERO
return leader.global_position + leader.global_transform.basis * offset
# 在智能体中使用编队系统
func _update_formation_state(delta):
var leader = get_formation_leader()
if leader:
var formation_pos = FormationSystem.calculate_formation_position(
leader,
get_formation_index(),
"V_SHAPE"
)
set_movement_target(formation_pos)
性能优化策略
空间分区优化
对于大规模群体模拟,空间分区是必要的性能优化手段:
class SpatialPartition:
var cell_size: float
var grid: Dictionary = {}
func _init(cell_size: float = 10.0):
self.cell_size = cell_size
func get_cell_key(position: Vector3) -> Vector3i:
return Vector3i(
floor(position.x / cell_size),
floor(position.y / cell_size),
floor(position.z / cell_size)
)
func add_agent(agent: Node3D):
var cell_key = get_cell_key(agent.global_position)
if not grid.has(cell_key):
grid[cell_key] = []
grid[cell_key].append(agent)
func remove_agent(agent: Node3D):
var cell_key = get_cell_key(agent.global_position)
if grid.has(cell_key):
grid[cell_key].erase(agent)
func get_nearby_agents(position: Vector3, radius: float) -> Array:
var center_cell = get_cell_key(position)
var search_radius = ceil(radius / cell_size)
var nearby: Array = []
for x in range(center_cell.x - search_radius, center_cell.x + search_radius + 1):
for y in range(center_cell.y - search_radius, center_cell.y + search_radius + 1):
for z in range(center_cell.z - search_radius, center_cell.z + search_radius + 1):
var cell_key = Vector3i(x, y, z)
if grid.has(cell_key):
for agent in grid[cell_key]:
if agent.global_position.distance_to(position) <= radius:
nearby.append(agent)
return nearby
更新频率优化
# 智能体管理器,控制更新频率
class AgentManager:
var agents: Array = []
var update_groups: Dictionary = {} # 按更新频率分组
func add_agent(agent: Node3D, update_rate: float = 0.1):
agents.append(agent)
var group_key = str(update_rate)
if not update_groups.has(group_key):
update_groups[group_key] = {"agents": [], "timer": 0.0, "rate": update_rate}
update_groups[group_key].agents.append(agent)
func update(delta: float):
for group_key in update_groups:
var group = update_groups[group_key]
group.timer += delta
if group.timer >= group.rate:
group.timer = 0.0
for agent in group.agents:
if is_instance_valid(agent):
agent.update_behavior()
调试与可视化
调试信息显示
extends Node3D
class_name DebugVisualizer
@export var show_path: bool = true
@export var show_velocity: bool = true
@export var show_neighbors: bool = true
@export var debug_color: Color = Color.YELLOW
var debug_mesh: ImmediateMesh
var debug_material: StandardMaterial3D
func _ready():
debug_mesh = ImmediateMesh.new()
debug_material = StandardMaterial3D.new()
debug_material.flags_unshaded = true
debug_material.vertex_color_use_as_albedo = true
var mesh_instance = MeshInstance3D.new()
mesh_instance.mesh = debug_mesh
mesh_instance.material_override = debug_material
add_child(mesh_instance)
func draw_agent_debug(agent: SwarmAgent):
debug_mesh.clear_surfaces()
if show_path and agent.navigation_agent:
var path = agent.navigation_agent.get_current_navigation_path()
debug_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP)
debug_mesh.surface_set_color(debug_color)
for point in path:
debug_mesh.surface_add_vertex(point)
debug_mesh.surface_end()
if show_velocity:
var start = agent.global_position
var end = start + agent.velocity.normalized() * 2.0
debug_mesh.surface_begin(Mesh.PRIMITIVE_LINES)
debug_mesh.surface_set_color(Color.GREEN)
debug_mesh.surface_add_vertex(start)
debug_mesh.surface_add_vertex(end)
debug_mesh.surface_end()
if show_neighbors:
for neighbor in agent.neighbors:
if is_instance_valid(neighbor):
debug_mesh.surface_begin(Mesh.PRIMITIVE_LINES)
debug_mesh.surface_set_color(Color.BLUE)
debug_mesh.surface_add_vertex(agent.global_position)
debug_mesh.surface_add_vertex(neighbor.global_position)
debug_mesh.surface_end()
实战案例:鸟群模拟系统
完整的鸟群模拟实现
extends Node3D
class_name BirdFlockSimulation
@export var flock_size: int = 20
@export var spawn_radius: float = 10.0
@export var bird_scene: PackedScene
var birds: Array = []
var spatial_partition: SpatialPartition
var agent_manager: AgentManager
func _ready():
spatial_partition = SpatialPartition.new(15.0)
agent_manager = AgentManager.new()
spawn_flock()
setup_navigation_environment()
func spawn_flock():
for i in range(flock_size):
var bird = bird_scene.instantiate()
var spawn_pos = global_position + Vector3(
randf_range(-spawn_radius, spawn_radius),
randf_range(5, 15),
randf_range(-spawn_radius, spawn_radius)
)
bird.global_position = spawn_pos
add_child(bird)
birds.append(bird)
spatial_partition.add_agent(bird)
agent_manager.add_agent(bird, randf_range(0.05, 0.2))
func setup_navigation_environment():
# 创建导航网格
var navigation
登录后查看全文
热门项目推荐
相关项目推荐
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0255
GLM-5.2智谱开源 GLM-5.2,这是针对长文本任务的最新旗舰模型。相较于前代产品 GLM-5.1,它在长文本任务处理能力上实现了显著飞跃,并且首次在稳定的 100 万 token 上下文中提供这一能力。Jinja00
JoyAI-VL-Interaction-Preview京东开源首个开源、视觉驱动的实时交互模型——它能实时监控视频流,并自主决定何时发言、保持沉默或委托任务。Jinja00
cann-learning-hubCANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。Jupyter Notebook0183
MaxKB强大易用的开源企业级智能体平台Python02
note-gen一款跨平台的 Markdown AI 笔记软件,致力于使用 AI 建立记录和写作的桥梁。TSX011
项目优选
收起
暂无描述
Dockerfile
787
5.17 K
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
900
2.09 K
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
721
1.45 K
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.14 K
1.18 K
deepin linux kernel
C
32
16
Ascend Extension for PyTorch
Python
768
995
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
472
482
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
2.51 K
689
CANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体,本仓库为其提供可复用的 Skills 模块。
Python
1.08 K
684
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.05 K
277