Deep RL 课程文档

Godot RL Agents

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Godot RL Agents

Godot RL Agents 是一个开源软件包,它为视频游戏创作者、AI 研究人员和爱好者提供了学习其非玩家角色或代理的复杂行为的机会。

该库提供:

  • Godot Engine 中创建的游戏与在 Python 中运行的机器学习算法之间的接口
  • 四个著名的 rl 框架的包装器:StableBaselines3CleanRLSample FactoryRay RLLib
  • 支持基于内存的代理,使用 LSTM 或基于注意力机制的接口
  • 支持 2D 和 3D 游戏
  • 一套 AI 传感器,以增强您的代理观察游戏世界的能力
  • Godot 和 Godot RL Agents 完全免费且开源,采用非常宽松的 MIT 许可证。没有任何附加条件,没有版税,什么都没有。

您可以在他们的 GitHub 页面 或他们的 AAAI-2022 Workshop 论文 上找到更多关于 Godot RL agents 的信息。该库的创建者 Ed Beeching 是 Hugging Face 的一名研究科学家。

库的安装很简单:pip install godot-rl

使用 Godot RL Agents 创建自定义 RL 环境

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

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

我们今天将构建的环境称为 Ring Pong,即乒乓球游戏,但场地是一个环形,球拍围绕环形移动。目标是保持球在环内弹跳

Ring Pong

安装 Godot 游戏引擎

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

Godot Engine 是一款功能丰富的跨平台游戏引擎,旨在从统一的界面创建 2D 和 3D 游戏。它提供了一套全面的常用工具,因此用户可以专注于制作游戏,而无需重新发明轮子。只需单击一下,游戏即可导出到多个平台,包括主要的桌面平台(Linux、macOS、Windows)以及移动平台(Android、iOS)和基于 Web 的(HTML5)平台。

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

为了在 Godot 中创建游戏,您必须首先下载编辑器。Godot RL Agents 支持最新版本的 Godot,Godot 4.0。

可以从以下链接下载

加载入门项目

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

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

如果您按下 F5 或在编辑器中播放,您应该能够在人类模式下玩游戏。有几个游戏实例在运行,这是因为我们想通过多个并行环境来加速训练我们的 AI 代理。

安装 Godot RL Agents 插件

Godot RL Agents 插件可以从 Github 仓库或编辑器中的 Godot Asset Lib 安装。

首先单击 AssetLib 并搜索 “rl”

Godot

然后单击 Godot RL Agents,单击下载并取消选择 LICENSE 和 README .md 文件。然后单击安装。

Godot

Godot RL Agents 插件现在已下载到您的机器。现在单击项目 → 项目设置并启用插件

Godot

添加 AI 控制器

我们现在想为我们的游戏添加一个 AI 控制器。打开 player.tscn 场景,在左侧您应该看到一个节点层次结构,如下所示

Godot

右键单击 Player 节点,然后单击添加子节点。此处列出了许多节点,搜索 AIController3D 并创建它。

Godot

AI 控制器节点应该已添加到场景树中,旁边有一个滚动条。单击它以打开附加到 AIController 的脚本。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 的单个连续值。

下一步是更新 Player 的脚本以使用来自 AIController 的动作,通过单击 player 节点旁边的滚动条来编辑 Player 的脚本,将 Player.gd 中的代码更新为以下内容

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 节点。此节点处理 Python 和 Godot 之间通过 TCP 的通信。

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

在这个简单的示例中,可以在几分钟内学习到合理的策略。您可能希望加快训练速度,单击 train 场景中的 Sync 节点,您将看到编辑器中公开了一个 “Speed Up” 属性

Godot

尝试将此属性设置为 8 以加快训练速度。这对于更复杂的环境(例如我们将在下一章中学习的多人 FPS)可能是一个巨大的好处。

导出模型

参考文档

现在让我们把 Godot 编辑器放在一边。我们需要使用终端来运行一些命令,以便保存我们训练的模型。

最新版本的 Godot RL 库为 Stable Baselines 3、rllib 和 CleanRL 训练框架提供了对 onnx 模型的实验性支持。

例如,让我们使用 Stable Baselines 3 作为框架。使用 sb3 示例 (使用脚本的说明) 训练您的代理,启用选项 --onnx_export_path=model.onnx

下面是一个要执行的命令行示例

cd <....> # go into this Godot project directory
python stable_baselines3_example.py --timesteps=100_000 --onnx_export_path=model.onnx --save_model_path=model.zip --save_checkpoint_frequency=20_000 --experiment_name=exp1

如果一切正常,您应该在终端中看到如下所示的消息

No game binary has been provided, please press PLAY in the Godot editor
waiting for remote GODOT connection on port 11008

如果您在 stable_baselines3_example 脚本中遇到关于导入错误的失败:“ImportError: cannot import name ‘export_model_as_onnx’ from ‘godot_rl.wrappers.onnx.stable_baselines_export’”,请按照 此问题 中的答案进行操作。

现在是时候切换回 Godot 编辑器,然后点击右上角的 PLAY。一旦您点击它,游戏场景将弹出,显示 AI 训练。同时,终端将开始打印指标。等待训练完成,如果一切正常,您应该能够在 Godot 项目目录中找到文件 model.onnx

在游戏中使用 AI!

现在让我们将这个训练好的模型应用到游戏中!

在 Godot 编辑器中,找到 train.tscn 中的 Sync 节点

  • 从下拉列表中将控制模式更改为 Onnx Inference
  • Onnx Model Path 设置为模型文件名,在这里我们的例子中是 model.onnx

要运行此游戏,我们需要 Godot 编辑器的 mono 版本(即 .NET 版本),您可以从 Godot 官方页面下载。我们还需要安装 .NET

在第一次尝试时,您很可能会遇到错误。以下是帮助您解决错误的情况。

  1. 关于 Invalid Call. Nonexistent function 'new' in base 'CSharpScript' 的问题:解决方案
  2. 关于 MacOS 上 onnxruntime 的错误:解决方案

还有更多!

我们仅仅触及了 Godot RL Agents 可以实现的冰山一角,该库包括自定义传感器和摄像头,以丰富代理可用的信息。查看示例以了解更多信息!

为了能够将训练好的模型导出到 .onnx,以便您可以直接从 Godot 运行推理而无需 Python 服务器,以及其他有用的训练选项,请查看高级 SB3 教程

作者

本节由 Edward Beeching 撰写

< > 在 GitHub 上更新