Godot RL 智能体

Godot RL 智能体是一个开源软件包,为视频游戏开发者、人工智能研究人员和爱好者提供了学习其非玩家角色(NPC)或智能体的复杂行为的机会。

该库提供了以下功能:

你可以在他们的 GitHub 页面或他们的 AAAI-2022 研讨会论文上了解更多关于 Godot RL 智能体的信息。该库的创建者Ed Beeching是 Hugging Face 的研究员。

安装该库非常简单:pip install godot-rl

使用 Godot RL 智能体创建自定义 RL 环境

在本节中,你将学习如何在 Godot 游戏引擎中创建自定义环境,然后实现一个深度强化学习的 AI 控制器。

我们今天创建的示例游戏很简单,但展示了 Godot 引擎和 Godot RL 智能体库的许多功能。你随后可以深入研究更复杂的环境和行为示例。

我们今天要构建的环境称为 Ring Pong,它是乒乓球游戏,但球场是一个环形,球拍在环上移动。目标是让球在环内持续弹跳

Ring Pong

安装 Godot 游戏引擎

Godot 游戏引擎是一个用于创建视频游戏、工具和用户界面的开源工具。

Godot 引擎是一个功能齐全的跨平台游戏引擎,旨在通过统一的界面创建 2D 和 3D 游戏。它提供了一套全面的常用工具,使用户可以专注于制作游戏,而无需重新造轮子。游戏可以一键导出到多个平台,包括主要的桌面平台(Linux、macOS、Windows),以及移动(Android、iOS)和基于 Web 的(HTML5)平台。

虽然我们将指导你实现智能体的步骤,但你可能希望了解更多关于 Godot 游戏引擎的信息。他们的文档非常详尽,YouTube 上也有许多教程,我们推荐 GDQuestKidsCanCodeBramwell 作为信息来源。

要在 Godot 中创建游戏,你首先必须下载编辑器。Godot RL 智能体支持最新版本的Godot,即Godot 4.0。

可以在以下链接处下载:

加载初始项目

我们提供了两个版本的代码库:

要加载项目,在Godot项目管理器中点击导入,导航到文件所在位置,并加载 project.godot 文件。

如果按下 F5 或在编辑器中播放,你应该能够以人类模式玩游戏。游戏有多个实例运行,这是因为我们希望通过许多并行环境加快训练AI智能体的速度。

安装 Godot RL 智能体插件

可以从 Github 仓库或使用 Godot 编辑器中的 Godot Asset Lib 安装 Godot RL 智能体插件。

首先点击 AssetLib,然后搜索 “rl”。

Godot

然后点开 Godot RL 智能体, 点击下载并筛除 LICENSE 和 README.md 文件,再安装。

Godot

Godot RL 智能体插件现在已经下载到你的机器上了。再点击 Project → Project settings 确保添加:

Godot

加入 AI 控制器

现在我们想要在游戏中添加一个 AI 控制器。打开 player.tscn 场景,你会看到左侧有一个节点层级,类似于这样:

Godot

右键点击 Player 节点,然后点击 Add Child Node 。这里列出了许多节点,搜索 AIController3D 并创建它。

Godot

AI 控制器节点应该已经添加到场景树中,在其旁边有一个滚动条。点击它以打开附加到 AI 控制器的脚本。Godot 游戏引擎使用一种名为 GDScript 的脚本语言,它在语法上类似于 Python。该脚本包含需要实现的方法,以使我们的 AI 控制器正常工作。

#-- Methods that need implementing using the "extend script" option in Godot --#
func get_obs() -> Dictionary:
	assert(false, "the get_obs method is not implemented when extending from ai_controller")
	return {"obs":[]}

func get_reward() -> float:
	assert(false, "the get_reward method is not implemented when extending from ai_controller")
	return 0.0

func get_action_space() -> Dictionary:
	assert(false, "the get get_action_space method is not implemented when extending from ai_controller")
	return {
		"example_actions_continous" : {
			"size": 2,
			"action_type": "continuous"
		},
		"example_actions_discrete" : {
			"size": 2,
			"action_type": "discrete"
		},
		}

func set_action(action) -> void:
	assert(false, "the get set_action method is not implemented when extending from ai_controller")
# -----------------------------------------------------------------------------#

为了实现这些方法,我们需要创建一个继承自 AIController3D 的类。在 Godot 中,这很容易做到,被称为“扩展”一个类。

右键单击 AIController3D 节点,然后单击“扩展脚本”,将新脚本命名为 controller.gd。现在你应该有一个几乎为空的脚本文件,看起来像这样:

extends AIController3D

# Called when the node enters the scene tree for the first time.
func _ready():
	pass # Replace with function body.

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	pass

我们现在将实现这 4 个缺失的方法,请删除这段代码并用以下代码替换:

extends AIController3D

# Stores the action sampled for the agent's policy, running in python
var move_action : float = 0.0

func get_obs() -> Dictionary:
	# get the balls position and velocity in the paddle's frame of reference
	var ball_pos = to_local(_player.ball.global_position)
	var ball_vel = to_local(_player.ball.linear_velocity)
	var obs = [ball_pos.x, ball_pos.z, ball_vel.x/10.0, ball_vel.z/10.0]

	return {"obs":obs}

func get_reward() -> float:
	return reward

func get_action_space() -> Dictionary:
	return {
		"move_action" : {
			"size": 1,
			"action_type": "continuous"
		},
		}

func set_action(action) -> void:
	move_action = clamp(action["move_action"][0], -1.0, 1.0)

我们现在定义了智能体的观测,即球在其本地坐标空间中的位置和速度。我们还定义了智能体的动作空间,这是一个从 -1 到 +1 的单一连续值范围。

下一步是更新播放器的脚本,以使用 AIController 的动作。通过点击播放器节点旁边的滚动条,编辑播放器的脚本,将代码更新为以下内容:

extends Node3D

@export var rotation_speed = 3.0
@onready var ball = get_node("../Ball")
@onready var ai_controller = $AIController3D

func _ready():
	ai_controller.init(self)

func game_over():
	ai_controller.done = true
	ai_controller.needs_reset = true

func _physics_process(delta):
	if ai_controller.needs_reset:
		ai_controller.reset()
		ball.reset()
		return

	var movement : float
	if ai_controller.heuristic == "human":
		movement = Input.get_axis("rotate_anticlockwise", "rotate_clockwise")
	else:
		movement = ai_controller.move_action
	rotate_y(movement*delta*rotation_speed)

func _on_area_3d_body_entered(body):
	ai_controller.reward += 1.0

现在我们需要在 Godot 中运行的游戏和 Python 中正在训练的神经网络之间进行同步。Godot RL Agents 提供了一个节点来完成这个任务。打开 train.tscn 场景,在根节点上右键单击,然后选择“添加子节点”。然后,在搜索框中搜索 “sync”,添加一个 Godot RL Agents Sync 节点。这个节点负责在 TCP 上处理 Python 和 Godot 之间的通信。

您可以在编辑器中实时运行训练,首先使用 gdrl 启动 Python 训练。

在这个简单的示例中,合理的策略可以在几分钟内学到。你可能希望加快训练速度,点击训练场景中的 Sync 节点,你会看到编辑器中暴露了一个名为 "Speed Up" 的属性:

Godot

尝试将此属性设置为 8 以加快训练速度。这在更复杂的环境中会带来很大的好处,比如我们将在下一章学习的多人射击游戏。

更多信息0!

这只是 Godot RL Agents 可以实现的一小部分。该库还包括自定义传感器和摄像头,以丰富代理可用的信息。请查看示例以获取更多信息!

作者

本节由 Edward Beeching 撰写