news 2026/9/20 11:06:39

从零创建 Unity 强化学习环境:ML-Agents RollerBall 环境构建与源码级实践指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零创建 Unity 强化学习环境:ML-Agents RollerBall 环境构建与源码级实践指南
  • 人工智能
  • 强化学习
  • 深度学习
  • 机器学习
  • 游戏开发
  • AI 应用

【免费下载链接】ml-agents

The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enables games and simulations to serve as environments for training intelligent agents using deep reinforcement learning and imitation learning.

项目地址:https://gitcode.com/gh_mirrors/ml/ml-agents
点击查看免费下载

本教程基于 ML-Agents 仓库中文文档《创建新的学习环境》,完整演示如何从空白 Unity 项目开始,构建一个可训练强化学习 agent 的物理模拟环境——RollerBall:一个需要滚动到随机放置的立方体目标、同时避免从平台上掉落的球体。读完本文,你将掌握学习环境的三大核心要素(Agent、行为策略、场景组织)、观测/动作/奖励的编码方法、环境的 Editor 配置与手动测试流程,并了解当前仓库(v4.1.0)与早期版本 API 的差异与迁移要点。

环境概览:我们将构建什么

本教程构建的 RollerBall 环境是一个最简单的强化学习任务:一个球(agent)在一个 10×10 的平台上滚动,学习到达随机放置的立方体(目标),并且不能从平台边缘掉落。这个环境虽然简单,却覆盖了 ML-Agents 学习环境设计的全部关键环节:

  • 物理组件:Plane(平台地板)、Cube(目标)、Sphere(agent,带 Rigidbody 刚体);
  • 逻辑组件:agent 的观测采集、动作执行与奖励计算代码;
  • 行为策略:决定 agent 如何根据观测产生动作的 Brain/Behavior 配置;
  • 训练接线:将环境连接到 Python 侧训练器。

版本说明:文档 API 与当前仓库的差异

在动手之前,有一个关键背景需要说明。本教程对应的原文档面向 ML-Agents 早期版本,其中使用了Academy组件、独立的Brain组件以及AgentReset()AgentAction()AddVectorObs()等旧 API。而当前仓库中com.unity.ml-agents包的版本为4.1.0(见 Academy.cs 中的k_PackageVersion常量),API 已发生较大变化:

维度早期版本(本文档所示)当前仓库 v4.1.0
Academy场景中的 GameObject 组件,需继承并挂载C# 单例类Academy.Instance,无需挂载组件(见 Academy.cs)
Brain独立 GameObject 组件,作为 Academy 子对象BehaviorParameters组件,直接挂在 Agent 所在游戏对象上(见 BehaviorParameters.cs)
环境重置AgentReset()OnEpisodeBegin()(见 Agent.cs)
接收动作AgentAction(float[] vectorAction, string textAction)OnActionReceived(ActionBuffers actions)(见 Agent.cs)
观测写入AddVectorObs(float)VectorSensor.AddObservation(...)(见 Agent.cs)
完成/重置Done()/ResetOnDone属性EndEpisode()/Max Step配置

本文会先完整保留原文档的操作流程与代码(标注为历史 API),再给出基于当前仓库 4.1.0 API 的对应实现,保证你在任一版本下都能落地。关于新旧 API 的系统性对照,可进一步阅读 迁移指南。

前置准备:安装与创建 Unity 项目

如果尚未安装 ML-Agents,请先按照 安装说明 完成 Unity 包、Python 训练环境(ml-agentsPython 包)的安装。

创建环境的第一步是新建一个 Unity 项目并引入 ML-Agents:

  1. 启动 Unity Editor,新建一个名为RollerBall的项目;
  2. 在文件系统中找到克隆的 ML-Agents 仓库文件夹;
  3. 将 ML-Agents 相关资源导入项目。

关于第 3 步需要说明:原文档描述的是将仓库unity-environments/Assets下的ML-Agents文件夹拖入 Unity Project 窗口。当前仓库的目录结构已调整,官方示例环境位于 Project/Assets/ML-Agents/Examples(包含 3DBall、Basic、Hallway、Walker 等 20 余个示例),包本体位于 com.unity.ml-agents,因此按官方推荐方式通过 Unity Package Manager 添加com.unity.ml-agents本地包即可。导入完成后,Unity 的Project窗口应能看到ML-Agents相关资源。

搭建物理场景

接下来创建充当环境的三件套:一个 Plane(agent 移动的底板)、一个 Cube(agent 追寻的目标)、一个 Sphere(agent 本身)。

创建地板(Floor):

  1. 在 Hierarchy 窗口右键,选择 3D Object > Plane;
  2. 命名为Floor
  3. 在 Inspector 中设置 Transform:Position = (0, 0, 0)、Rotation = (0, 0, 0)、Scale = (1, 1, 1);
  4. 在 Plane 的 Mesh Renderer 上展开 Materials,将默认材质替换为floor材质(点击材质名旁的小圆圈图标可打开 Object Picker 对话框,从项目现有材质列表中选择)。

添加目标立方体(Target):

  1. Hierarchy 中右键,选择 3D Object > Cube;
  2. 命名为Target
  3. Transform 设置为 Position = (3, 0.5, 3)、Rotation = (0, 0, 0)、Scale = (1, 1, 1);
  4. 将 Mesh Renderer 的默认材质替换为block材质。

添加 Agent 球体(RollerAgent):

  1. Hierarchy 中右键,选择 3D Object > Sphere;
  2. 命名为RollerAgent
  3. Transform 设置为 Position = (0, 0.5, 0)、Rotation = (0, 0, 0)、Scale = (1, 1, 1);
  4. 将材质替换为checker 1
  5. 点击Add Component,添加 Physics/Rigidbody 组件。

Rigidbody 是 Unity 物理模拟的核心组件,agent 将借助它被力推动(后续会通过Rigidbody.AddForce施力),这也是原文档要求添加它的原因。稍后我们会再创建一个 Agent 子类挂到这个球体上。

组织场景层级:

  1. Hierarchy 中右键,选择 Create Empty,命名为Academy
  2. 右键 Academy 游戏对象,再选择 Create Empty,将其子级命名为Brain

这是早期版本要求的场景结构(Academy 作为 Brain 的父级)。在当前 v4.1.0 中,场景层级已大幅简化:不再需要 Academy 与 Brain 游戏对象,Agent 游戏对象上直接挂BehaviorParameters组件即可。原文档此处的步骤可以理解为理解"环境-决策"分层关系的历史视角。下文"实现 Academy"与"添加 Brain"两节会分别说明新旧两种做法。

实现 Academy:环境级协调者

Academy 负责协调场景中的 ML-Agents 运行并驱动模拟中的决策环节。早期版本中,每个 ML-Agents 场景需要一个 Academy 实例,且由于基类是抽象类,即使不需要任何定制也必须创建子类:

  1. 选中 Academy 游戏对象;
  2. 点击Add Component,选择New Script
  3. 命名为RollerAcademy,点击Create and Add
  4. 双击脚本,将基类从MonoBehaviour改为Academy,删除默认的Start()Update()方法。

对于这种简单场景,Academy 不需要初始化或重置任何对象,因此采用最简实现:

public class RollerAcademy : Academy { }

Academy 的默认属性设置已满足本环境需求,无需在 Inspector 中额外修改。

当前 v4.1.0 的做法:Academy 已从 GameObject 组件演变为 C# 单例类,通过Academy.Instance访问(见 Academy.cs)。你不再需要创建 Academy 子类、也不需要往场景里放 Academy 游戏对象。如果需要每局开始前重置环境级对象(例如移动障碍物、重置多个 agent 的共同状态),官方推荐订阅Academy.Instance.OnEnvironmentReset事件(参见 Learning-Environment-Design.md 中的示例):

public class MySceneBehavior : MonoBehaviour { public void Awake() { Academy.Instance.OnEnvironmentReset += EnvironmentReset; } void EnvironmentReset() { // 在这里重置整个场景 } }

本教程的 RollerBall 将重置逻辑放在 Agent 内部,因此两种版本都不需要额外场景级重置代码。

添加 Brain / 行为参数:封装决策过程

早期版本中,Brain 对象封装决策过程:Agent 把观测发给自己的 Brain 并等待决策返回。Brain 不需要继承子类,直接添加组件即可:

  1. 选中Brain游戏对象;
  2. 点击Add Component,选择Scripts/Brain组件。

当前 v4.1.0 的做法:Brain 组件已被 BehaviorParameters.cs 组件取代,它直接挂在 Agent 游戏对象上,运行时根据 Inspector 中的设置生成对应策略(Policy)对象。策略类型由BehaviorType枚举决定(见 BehaviorParameters.cs):

  • Default:优先连接 Python 远程训练进程;不可用时回退到推理(使用模型);再无模型则使用 Heuristic;
  • HeuristicOnly:始终使用手动/脚本控制逻辑;
  • InferenceOnly:始终使用已导入的神经网络模型(ONNX)推理,未指定模型时会抛出异常。

这与早期版本中External(训练)、Player(手动控制)、Internal(内置模型推理)三种 Brain Type 的职责一一对应。我们稍后会分别在"测试环境"与"训练准备"两节切换使用它们。

实现 Agent:核心编码

Agent 子类定义了 agent 观测环境、执行动作、计算奖励所需的全部代码。创建步骤:

  1. 选中 RollerAgent 游戏对象,点击Add Component,选择New Script
  2. 命名为RollerAgent,点击Create and Add
  3. 双击脚本,将基类从MonoBehaviour改为Agent
  4. 删除Update()方法(保留Start(),用于获取组件引用)。

初始化和重置 Agent

Agent 到达目标时将自己标记为完成,重置函数将目标移动到随机位置;如果 agent 从平台滚下(y < -1),重置函数将其放回地板中央并清零速度。

为了移动目标,需要持有目标 GameObject 的Transform引用(存储物体在 3D 世界中的位置、旋转与缩放);公共字段会显示在 Inspector 中,可以直接把 Target 游戏对象拖拽进来赋值。为了重置速度(以及稍后施力),需要引用Rigidbody组件——由于它与 Agent 脚本位于同一游戏对象,最佳获取方式是在Start()中调用GetComponent<Rigidbody>()

早期版本的初始化和重置代码如下:

using System.Collections.Generic; using UnityEngine; public class RollerAgent : Agent { Rigidbody rBody; void Start () { rBody = GetComponent<Rigidbody>(); } public Transform Target; public override void AgentReset() { if (this.transform.position.y < -1.0) { // agent 掉落 this.transform.position = Vector3.zero; this.rBody.angularVelocity = Vector3.zero; this.rBody.velocity = Vector3.zero; } else { // 将目标移动到新的位置 Target.position = new Vector3(Random.value * 8 - 4, 0.5f, Random.value * 8 - 4); } } }

当前 v4.1.0 的对应实现:组件引用获取放在Initialize()中(在 agent 首次启用时调用一次),单局重置逻辑放在OnEpisodeBegin()中。Agent的完整生命周期为:Initialize()→ 每局OnEpisodeBegin()→ 每步CollectObservations()OnActionReceived()(参见 Learning-Environment-Design.md 中描述的 Academy 模拟循环)。新版本对应的代码如下:

using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Actuators; using Unity.MLAgents.Sensors; using Random = UnityEngine.Random; public class RollerAgent : Agent { Rigidbody m_RBody; public Transform Target; public float speed = 10; float m_PreviousDistance = float.MaxValue; public override void Initialize() { m_RBody = GetComponent<Rigidbody>(); } public override void OnEpisodeBegin() { if (transform.position.y < -1.0f) { // agent 掉落:回到原点并清零速度 transform.position = Vector3.zero; m_RBody.angularVelocity = Vector3.zero; m_RBody.linearVelocity = Vector3.zero; } else { // 将目标移动到随机位置 Target.position = new Vector3(Random.value * 8 - 4, 0.5f, Random.value * 8 - 4); } m_PreviousDistance = float.MaxValue; } // CollectObservations / OnActionReceived / Heuristic 见下文各节 }

观测环境:CollectObservations

Agent 将采集到的信息发送给策略(Brain),由策略基于这些信息做决策。训练(或使用已训练模型推理)时,这些数据作为特征向量输入神经网络。为了让 agent 成功学习任务,必须提供正确的信息——一个实用的经验法则是:思考如果要手工求解这个问题需要哪些量

本示例中 agent 收集三类信息,共 8 个连续值:

1. 目标相对位置(2 个值)。为了泛化,应使用相对位置而非绝对位置。只取 x、z 分量,因为地板平行于 x-z 平面,y 分量不变:

Vector3 relativePosition = Target.position - this.transform.position; AddVectorObs(relativePosition.x / 5); AddVectorObs(relativePosition.z / 5);

2. 距平台边缘的距离(4 个值)。分别采集 agent 到地板四边的距离,帮助它避免滚落:

AddVectorObs((this.transform.position.x + 5) / 5); AddVectorObs((this.transform.position.x - 5) / 5); AddVectorObs((this.transform.position.z + 5) / 5); AddVectorObs((this.transform.position.z - 5) / 5);

3. Agent 速度(2 个值)。帮助 agent 学会控制速度,避免冲过目标或滚下平台:

AddVectorObs(rBody.velocity.x / 5); AddVectorObs(rBody.velocity.z / 5);

所有值除以 5 是将神经网络输入归一化到 [-1, 1](平台跨度为 10 个单位,所以取半宽 5)。归一化可以避免个别大数值特征主导梯度更新,是环境设计中的通用实践。当前版本文档也明确建议:所有输入归一化到 0~+1 或 -1~+1 区间(见 Learning-Environment-Design-Agents.md)。

早期版本完整的CollectObservations()

List<float> observation = new List<float>(); public override void CollectObservations() { // 计算相对位置 Vector3 relativePosition = Target.position - this.transform.position; // 相对位置 AddVectorObs(relativePosition.x/5); AddVectorObs(relativePosition.z/5); // 与平台边缘的距离 AddVectorObs((this.transform.position.x + 5)/5); AddVectorObs((this.transform.position.x - 5)/5); AddVectorObs((this.transform.position.z + 5)/5); AddVectorObs((this.transform.position.z - 5)/5); // Agent 速度 AddVectorObs(rBody.velocity.x/5); AddVectorObs(rBody.velocity.z/5); }

当前 v4.1.0 的对应实现CollectObservations(VectorSensor sensor)通过sensor.AddObservation()写入观测(见 Agent.cs)。AddObservation提供了多种重载,可直接添加floatintboolVector2Vector3Quaternion等类型(参见 Learning-Environment-Design-Agents.md)。8 个观测值合计如下:

public override void CollectObservations(VectorSensor sensor) { // 目标相对位置 Vector3 relativePosition = Target.position - transform.position; sensor.AddObservation(relativePosition.x / 5f); sensor.AddObservation(relativePosition.z / 5f); // 与平台边缘的距离 sensor.AddObservation((transform.position.x + 5f) / 5f); sensor.AddObservation((transform.position.x - 5f) / 5f); sensor.AddObservation((transform.position.z + 5f) / 5f); sensor.AddObservation((transform.position.z - 5f) / 5f); // Agent 速度 sensor.AddObservation(m_RBody.linearVelocity.x / 5f); sensor.AddObservation(m_RBody.linearVelocity.z / 5f); }

务必保证观测数量与顺序始终一致。若环境中的可观测实体数量会变化,需要对缺失实体补 0 填充,或只观测固定子集(例如只取最近的 5 个敌人)。同时,Inspector 中 Behavior Parameters 的Vector Observations > Space Size必须等于CollectObservations()写入的浮点数个数——本环境为 8。

动作:从 vectorAction 到 ActionBuffers

策略的决策以动作数组形式传给 Agent。数组元素个数由策略的Vector Action Space TypeVector Action Space Size决定。RollerAgent 使用连续动作空间,需要两个连续控制信号:action[0]沿 x 轴施力,action[1]沿 z 轴施力(若要三维移动则设为 3)。注意:策略本身并不知道动作数组的语义,训练过程只是根据观测输入调整动作值并观察奖励回报。

早期版本通过AgentAction()接收动作,使用Rigidbody.AddForce施力:

Vector3 controlSignal = Vector3.zero; controlSignal.x = Mathf.Clamp(action[0], -1, 1); controlSignal.z = Mathf.Clamp(action[1], -1, 1); rBody.AddForce(controlSignal * speed);

将动作值限制在 [-1, 1] 有两个原因:其一,学习算法没有动机尝试极大值(因为不会对行为产生额外影响),可避免神经网络计算中的数值不稳定;其二,没有其他机制阻止网络输出过大的值,因此要在任何情况下都钳制在合理范围。

当前 v4.1.0 的对应实现OnActionReceived(ActionBuffers actionBuffers)中通过actionBuffers.ContinuousActions访问连续动作数组(离散动作对应DiscreteActions)。连续动作数组长度等于 Behavior Parameters 中Actions > Continuous Actions的设置值(参见 Learning-Environment-Design-Agents.md)。动作的完整实现合并进下文最终代码。

奖励设计:强化学习的核心

强化学习必须有奖励。奖励在动作接收函数中分配,学习算法利用每一步的奖励判断动作是否最优。设计原则:完成任务时给予正奖励,彻底失败(掉落)时给予惩罚;还可以用子奖励引导中间行为以加速收敛——例如本环境对"接近目标"给予小奖励,并对每个步进给予很小的负奖励以鼓励尽快完成。

RollerAgent 的奖励体系:

1. 到达目标:+1.0 并结束本局

float distanceToTarget = Vector3.Distance(this.transform.position, Target.position); if (distanceToTarget < 1.42f) { Done(); AddReward(1.0f); }

注意:agent 被标记为完成(Done)后会停止活动,直到被重置。早期版本可通过 Inspector 中的Agent.ResetOnDone属性让它在完成时立即重置,也可以等待 Academy 自己重置环境。本环境的重置依赖ResetOnDone机制,且 Academy 未设置Max Steps,因此 Academy 不会自行重置。

2. 进一步接近目标:+0.1(保存上一步的距离测量值作对比)

if (distanceToTarget < previousDistance) { AddReward(0.1f); }

3. 时间惩罚:每步 -0.05,鼓励快速完成

AddReward(-0.05f);

4. 掉下平台:-1.0 并结束本局

if (this.transform.position.y < -1.0) { Done(); AddReward(-1.0f); }

早期版本完整的AgentAction()

public float speed = 10; private float previousDistance = float.MaxValue; public override void AgentAction(float[] vectorAction, string textAction) { // 奖励 float distanceToTarget = Vector3.Distance(this.transform.position, Target.position); // 已到达目标 if (distanceToTarget < 1.42f) { Done(); AddReward(1.0f); } // 进一步接近 if (distanceToTarget < previousDistance) { AddReward(0.1f); } // 时间惩罚 AddReward(-0.05f); // 掉下平台 if (this.transform.position.y < -1.0) { Done(); AddReward(-1.0f); } previousDistance = distanceToTarget; // 动作,大小 = 2 Vector3 controlSignal = Vector3.zero; controlSignal.x = Mathf.Clamp(vectorAction[0], -1, 1); controlSignal.z = Mathf.Clamp(vectorAction[1], -1, 1); rBody.AddForce(controlSignal * speed); }

其中speed是公共字段,可在 Inspector 中直接调整;previousDistance是私有字段,用于记录上一步的距离。

当前 v4.1.0 的对应实现Done()对应EndEpisode(),调用后会在下一轮触发OnEpisodeBegin();单步奖励累加用AddReward(),直接覆盖累计奖励用SetReward()(当前版本文档也提示:需要提前结束 agent 时优先考虑禁用/销毁对象而非调用EndEpisode(),以避免对多 agent 编队训练造成意外重置,见 Learning-Environment-Design-Agents.md):

public override void OnActionReceived(ActionBuffers actionBuffers) { float distanceToTarget = Vector3.Distance(transform.position, Target.position); // 已到达目标 if (distanceToTarget < 1.42f) { AddReward(1.0f); EndEpisode(); } // 进一步接近 if (distanceToTarget < m_PreviousDistance) { AddReward(0.1f); } // 时间惩罚 AddReward(-0.05f); // 掉下平台 if (transform.position.y < -1.0f) { AddReward(-1.0f); EndEpisode(); } m_PreviousDistance = distanceToTarget; // 动作,大小 = 2 var continuousActions = actionBuffers.ContinuousActions; Vector3 controlSignal = Vector3.zero; controlSignal.x = Mathf.Clamp(continuousActions[0], -1f, 1f); controlSignal.z = Mathf.Clamp(continuousActions[1], -1f, 1f); m_RBody.AddForce(controlSignal * speed); }

现代示例对照:仓库中的 Ball3DAgent

仓库自带的 3DBall 示例是 RollerBall 思路的现代版本(平台改为可倾斜的板、球改为受重力滚动的目标),其完整实现位于 Project/Assets/ML-Agents/Examples/3DBall/Scripts/Ball3DAgent.cs,是学习新 API 写法的绝佳参考:

  • Initialize():获取球的 Rigidbody 与Academy.Instance.EnvironmentParameters(用于环境参数随机化);
  • CollectObservations(VectorSensor sensor):写入板倾角(rotation.z/x)、球相对位置、球速度——共 8 个值;
  • OnActionReceived(ActionBuffers actionBuffers):把两个连续动作钳制到 [-1,1] 后乘以 2 作为倾角增量;球掉落时SetReward(-1f)EndEpisode(),否则每步SetReward(0.1f)
  • OnEpisodeBegin():随机化板与球的初始姿态,保证训练泛化;
  • Heuristic(in ActionBuffers actionsOut):用Input.GetAxis把键盘输入写入动作数组,实现手动测试。

其中奖励思路与 RollerBall 完全同构(任务完成/失败大奖励 + 持续小奖励),你可以直接对照阅读。训练它的 PPO 配置见 config/ppo/3DBall.yaml。

最终 Editor 设置:把一切串起来

所有游戏对象与组件就绪后,在 Unity Editor 中完成接线。早期版本需要:

  1. 在 Hierarchy 中展开 Academy,使 Brain 对象可见;
  2. 选中 RollerAgent,将 Brain 对象从 Hierarchy 拖到其 Brain 字段;
  3. 将 Target 游戏对象拖到 RollerAgent 的 Target 字段;
  4. 选中 Brain 对象,设置以下属性:
属性
Vector Observation Space TypeContinuous
Vector Observation Space Size8
Vector Action Space TypeContinuous
Vector Action Space Size2
Brain TypePlayer(先用于手动测试)

当前 v4.1.0 的对应设置:选中 RollerAgent 游戏对象,添加Behavior Parameters组件并配置:

  • Vector Observations:Space Type = Continuous,Space Size = 8;
  • Actions:Continuous Actions = 2;
  • Behavior Type:先设为Heuristic Only用于手动测试,训练时改为Default
  • 将 Target 游戏对象拖到 RollerAgent 脚本的 Target 字段(speed也可在此调整)。

对应关系:Vector Observation Space Size=CollectObservations()写入的观测数(8);Continuous Actions= 动作数组长度(2)。若两者与代码不一致,训练或运行时会产生传感器形状不匹配错误。

测试环境:手动控制与 Heuristic

开始长时间训练前手动测试环境永远是明智之举。早期版本通过将Brain Type设为Player实现键盘直接控制:首先把按键定义为动作映射。虽然 RollerAgent 的动作维度只有 2,但每个动作用一个键指定正值、一个键指定负值,因此总共需要 4 个键:

  1. 选中 Brain 对象,将Brain Type设为Player
  2. 展开Continuous Player Actions(仅 Player Brain 可见),将Size设为 4;
  3. 设置如下映射:
元素索引
元素 0D01
元素 1A0-1
元素 2W11
元素 3S1-1

其中Index对应传给动作接收函数的动作数组索引,Value是按键按下时赋给action[Index]的值。

点击Play运行场景,用 WASD 控制 agent 在平台上移动,确认 Console 无报错、agent 到达目标或掉落时会重置。对于更复杂的调试,ML-Agents 还提供 Monitor 类,可在 Game 窗口中可视化 agent 状态信息。

当前 v4.1.0 的做法:不再需要按键映射表,而是在 Agent 中覆写Heuristic(in ActionBuffers actionsOut),直接读取输入写入动作数组(这正是BehaviorType.HeuristicOnly的用途)。示例可参考 Ball3DAgent.cs:

public override void Heuristic(in ActionBuffers actionsOut) { var continuousActionsOut = actionsOut.ContinuousActions; continuousActionsOut[0] = -Input.GetAxis("Horizontal"); continuousActionsOut[1] = Input.GetAxis("Vertical"); }

RollerAgent 可按相同模式实现:actionsOut.ContinuousActions[0] = Input.GetAxis("Horizontal");actionsOut.ContinuousActions[1] = Input.GetAxis("Vertical");

完成手动测试后,还可以用 Python API 做一次端到端验证:参考仓库 colab/Colab_UnityEnvironment_1_Run.ipynb,将env_name设置为本环境构建出的可执行文件名称,确认环境与 Python API 能正常通信。

训练准备:切换训练模式并启动训练

早期版本中,训练前必须把Brain TypePlayer改为External,之后按 训练 ML-Agents 中的流程执行训练。

当前 v4.1.0 的做法:将Behavior Type设为Default(远程训练进程可用时自动走训练,否则回退到 Heuristic,见 BehaviorParameters.cs),然后通过mlagents-learn命令启动训练。训练配置使用 YAML 文件,以 config/ppo/3DBall.yaml 为模板:

behaviors: 3DBall: trainer_type: ppo hyperparameters: batch_size: 64 buffer_size: 12000 learning_rate: 0.0003 beta: 0.001 epsilon: 0.2 lambd: 0.99 num_epoch: 3 learning_rate_schedule: linear network_settings: normalize: true hidden_units: 128 num_layers: 2 vis_encode_type: simple reward_signals: extrinsic: gamma: 0.99 strength: 1.0 keep_checkpoints: 5 max_steps: 500000 time_horizon: 1000 summary_freq: 12000

要点说明:behaviors下每个键对应一个 Behavior Name(须与 Unity 中 Behavior Parameters 的 Behavior Name 一致);trainer_type可选pposacpoca等(仓库 config 目录按算法分别存放了各环境的配置);network_settings.normalize: true对应本教程中手工除以 5 的归一化思路——配置层会自动对观测做归一化;max_steps控制总训练步数上限。训练中断后如需继续,可使用--resume参数;训练完成的模型为.onnx文件,导入 Unity 后选择Inference OnlyDefault类型并挂载模型即可在游戏内推理(参见 Inference-Engine.md)。

回顾:场景布局

使用 ML-Agents 构建学习环境,需要理解场景中的三类核心要素及其组织方式:

早期版本要求:

  • Academy:场景中只能有一个 Academy 游戏对象;
  • Brain:可以有多个 Brain 游戏对象,但必须是 Academy 的子级;
  • Agent:实现 Agent 子类并挂到表示 agent 的游戏对象上。

当前 v4.1.0 中组织方式已简化为:Agent 游戏对象 + BehaviorParameters 组件(可多个 Agent 共享同一 Behavior Name 实现多智能体并行训练;如需在同一场景中训练多个不同任务,则使用多个 Behavior Name)。一个训练用场景还需要满足三个条件:被训练进程启动时能自动运行起始场景;每局训练开始时场景处于合法起始状态(通过OnEpisodeBeginOnEnvironmentReset保证);每局有明确结束方式(Max Step上限或 Agent 调用EndEpisode())——详见 Learning-Environment-Design.md。

小结与延伸

至此,一个完整的 RollerBall 学习环境已构建完成:从场景搭建、Agent 编码(观测→动作→奖励)、Editor 接线、手动测试到训练配置,覆盖了 ML-Agents 环境开发的全流程。无论你使用早期版本的 Academy/Brain 组件,还是当前仓库 v4.1.0 的BehaviorParameters组件与新 Agent API,核心设计思想一致:提供充分的归一化观测、定义清晰的奖励信号、保证每局可重置可结束

后续可以继续阅读 创建新的学习环境(当前版本官方文档) 与 设计 Agent 深入了解观测生成(Camera/Grid/RayPerception 传感器)、离散动作、Actuator API 与多智能体团队等进阶主题,并对照仓库 Examples 中 20 余个示例环境学习不同任务的实现模式。

  • 人工智能
  • 强化学习
  • 深度学习
  • 机器学习
  • 游戏开发
  • AI 应用

【免费下载链接】ml-agents

The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enables games and simulations to serve as environments for training intelligent agents using deep reinforcement learning and imitation learning.

项目地址:https://gitcode.com/gh_mirrors/ml/ml-agents
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 11:02:40

secsgem-master实战:从SECS协议骨架到S1F13消息收发

简介&#xff1a;这是以Python语言实现的SECS/GEM半导体通信协议开源项目&#xff0c;面向设备自动化工程师、协议研究与工业上位机开发者&#xff0c;重点展示SECS I与SECS II层次下的数据编解码、消息交互、文件传输及事件通知机制&#xff0c;并涵盖了同步与定时处理、异常与…

作者头像 李华
网站建设 2026/9/20 11:00:45

单片机抄表系统实战:DL/T 645 帧解析、RS-485 组网与掉电存储

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 11:00:35

自建CRM系统选型:从数据归属到销售自动化的完整落地指南

很多团队在选型客户管理系统时&#xff0c;都会碰到一个很现实的问题&#xff1a;市面上的SaaS类CRM看似功能全面&#xff0c;但用久了总感觉像在别人的地盘上盖房子。数据不在自己手里&#xff0c;敏感客户资料理论上能被平台访问&#xff0c;想定制个字段和流程又受制于厂商的…

作者头像 李华
网站建设 2026/9/20 10:58:47

220kV降压变电所电气一次部分初步设计要点解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 10:54:31

用Skills重构AI编程工作流:软件研发全生命周期的技能包实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华